JS学习笔记12_优化

一.可维护性优化

1.添加注释

注释能够增强代码的可读性以及可维护性,当然,理想情况是满满的注释,但这不太现实。所以我们只需要在一些关键的地方添上注释:

  • 函数和方法:尤其是返回值,因为直接看不出来
  • 大段代码(功能模块):说明模块功能
  • 复杂算法:写出关键点,方便理解
  • Hack:说明为了修复什么问题,当前方案是否完善,能否改进

2.“暗示”变量类型

通过初始值来暗示,例如:

var found = false;
var count = 1;
var name = ‘‘;
var student = null;

3.解耦(分层)

  • 结构层:HTML
  • 行为层:JS
  • 表现层:CSS

尽量不要“越权”,如果实在是想越权,也应该用文档或者注释说明。尽量不要出现紧耦合,例如:

  • JS-HTML:

    elem.innerHTML = ‘<div class="block"><h2>title</h2><p>content</p></div>‘;
    //最好用下面的方式代替(显示页面中的隐藏元素)
    //elem.style.display = ‘block‘;
  • JS-CSS:
    elem.style.color = ‘#e0e0e0‘;
    //最好用下面的方式代替(设置类,不要直接设置样式)
    //elem.className = ‘my_class‘;
  • JS-JS:
    //逻辑耦合
    elem.onclick = function(e){
      if(txt.value !== null && txt.value !== ‘‘ &&...){
        //DOM操作
      }
    }
    //最好用下面的方式代替(分离逻辑功能块)
    function isValid(){
      return txt.value !== null && txt.value !== ‘‘ &&...;
    }
    function display(){
      //DOM操作
    }
    elem.onclick = function(e){
      if(isValid()){
        display();
      }
    }

    避免逻辑耦合的几条原则:

    • 不要传递event对象,只传需要的数据
    • 触发事件不应该是执行动作的唯一方式
    • 事件处理器应该只处理事件相关数据(获取事件源,坐标值等等),然后把处理转交给应用逻辑

4.编码原则

  • 尊重对象所有权,不要随便修改别人的对象,具体要求:

    • 不要给实例/原型添加属性或方法
    • 不要重写已存在的方法

    可选方案:

    • 组合:创建实现了所需功能的新对象,引用需要的对象
    • 继承:创建自定义类型,继承需要修改的类型,然后添加额外功能
  • 用命名空间避免全局变量,例如:
    var mySystem = {};
    mySystem.mod1 = {...};
  • 用常量提高可维护性,例如:
    var Consts = {};
    Consts.IMG_PATH = ‘../imgs/‘;

    注意:常量包括常用的CSS类名和其它任何可能影响维护的值

二.性能优化

1.避免长作用域链查找

把需要多次引用的全局变量另存为局部变量

2.尽量不要用with语句

with语句会延长作用域,存在长作用域查找的开销,可以用另存局部变量来代替(没有with方便,但多少能好一点)

3.避免不必要的属性查找

  1. 尽量把重复使用的值另存为局部变量,例如:

    //不要用下面的代码(6次属性查找)
    var qs = window.location.href.substring(window.location.href.indexOf(‘?‘));
    //应该用下面的代码(4次,而且更具可读性)
    var url = window.location.href;
    var qs = url.substring(url.indexOf(‘?‘));
  2. 优化循环
    • 减值迭代更快(i–)
    • 简化终止条件,每次循环都会检查终止条件,简化条件能提高效率
    • 简化循环体,尽量减少循环体里面的计算量
    • 使用后测试循环(do...while),可以避免第一次循环前的判断
  3. 展开循环

    如果循环次数确定,最好不要用循环,因为循环存在创建循环和处理终止条件的额外开销,例如:

    for(i = 0;i < 2;i++){
      process(arr[i]);
    }
    //下面的比上面的快
    process(arr[0]);
    process(arr[1]);
    process(arr[2]);

    如果循环次数不能确定,可以用Duff技术(Tom Duff发明的)展开一部分循环,提高效率,例如:

    //credit: Jeff Greenberg for JS implementation of Duff’s Device
    //假设 values.length > 0
    var iterations = Math.ceil(values.length / 8);
    var startAt = values.length % 8;
    var i = 0;
    do {
        switch(startAt){
            case 0: process(values[i++]);
            case 7: process(values[i++]);
            case 6: process(values[i++]);
            case 5: process(values[i++]);
            case 4: process(values[i++]);
            case 3: process(values[i++]);
            case 2: process(values[i++]);
            case 1: process(values[i++]);
        }
        startAt = 0;
    } while (--iterations > 0);
    //以上代码来自:http://www.cnblogs.com/kylindai/archive/2013/12/04/3458476.html

    或者另一个更快的Duff方法:

    //credit: Speed Up Your Site (New Riders, 2003)
    var iterations = Math.floor(values.length / 8);
    var leftover = values.length % 8;
    var i = 0;
    if (leftover > 0){
        do {
            process(values[i++]);
        } while (--leftover > 0);
    }
    do {
        process(values[i++]);
        process(values[i++]);
        process(values[i++]);
        process(values[i++]);
        process(values[i++]);
        process(values[i++]);
        process(values[i++]);
        process(values[i++]);
    } while (--iterations > 0);
    //以上代码来自:http://www.cnblogs.com/kylindai/archive/2013/12/04/3458476.html
  4. 避免双重解释

    双重解释是指:用js解析js。具体是用eval()函数或者new Function(strCode)或者setTimeout(strCode)

    双重解释的缺点:需要再启动一个解析器来解析,存在很大的开销,比直接解析慢很多

  5. 原生方法更快

    原生方法是用用C/C++编译好的模块,所以要快得多

  6. switch比if-else快

    原因不好说,可以参考CSDN

  7. 位运算并没有更快

    在其它语言中把数学运算简化为位运算能够提升计算速度,但js中没这一说,因为js内部只有一种数值类型(double),所以做位运算需要折腾:double – int – 做位运算 – double,性能可想而知

  8. 减少语句数量
    • 用1个var声明多个变量
    • 插入迭代值,arr[i++]一条语句搞定,不用把i++独立成一个语句
    • 用数组/对象字面量,代码行数明显变少了
  9. DOM优化
    • 减少现场更新,可以用DocumentFragment优化
    • 用innerHTML创建DOM节点比创建一堆节点再组装要快,但存在JS-HTML耦合问题,慎重考虑
    • 用事件委托
    • 注意实时更新的集合(NodeList、NamedNodeMap、HTMLCollection)

      除了把引用另存为局部变量外,还要注意访问其属性也是需要重新查询的,比如:var imgs = document.images;访问imgs.length也需要再查一次

三.发布优化

  1. 用验证工具(如JSLint)检查代码,发现语法错误之外的潜在问题
  2. 去掉注释(出于安全性考虑)
  3. 合并js文件,尽量减少外部文件数量
  4. 压缩代码(如YUI压缩器),减少代码本身大小,也可以同时混淆代码,提高安全性,但混淆代码本身存在风险,可能引发错误
  5. 开启服务器压缩功能,例如gzip模块
时间: 2024-08-26 21:54:37

JS学习笔记12_优化的相关文章

JS学习笔记-OO疑问之对象创建

问一.引入工厂,解决重复代码 前面已经提到,JS中创建对象的方法,不难发现,基本的创建方法中,创建一个对象还算简单,如果创建多个类似的对象的话就会产生大量重复的代码. 解决:工厂模式方法(添加一个专门创建对象的方法,传入参数避免重复) function createObject(name,age){ var obj =new Object(); //创建对象 obj.name = name; obj.age = age; obj.run = function(){ return this.nam

仿知乎日报学习笔记与优化

仿知乎日报学习笔记与优化项目原地址(有些小BUG):单页网页应用:https://github.com/pomelo-chuan/Zhihu-Daily-Vue.js知乎日报api查询:https://github.com/izzyleung/ZhihuDailyPurify/wiki/%E7%9F%A5%E4%B9%8E%E6%97%A5%E6%8A%A5-API-%E5%88%86%E6%9E%90如果想看完整的API的json数据的话,推荐使用sublime,网上搜索sublime jso

Vue.js学习笔记:在元素 和 template 中使用 v-if 指令

f 指令 语法比较简单,直接上代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title></title> <script src="https://cdn.bootcss.com/vue/2.2.

[Pro Angular.JS]学习笔记1.1:设置开发环境

可以使用yeoman.io,很方便.我已经写了一篇随笔,介绍如何使用.这里也有一篇介绍的文章:http://www.cnblogs.com/JoannaQ/p/3756281.html 代码编辑器,在Mac下用了一下WebStorm,太恶心了.另外发现书的作者使用的开发环境是Windows + VS Express 2013,为了方便学习,我也使用VS Express 2013 Update2.VS2013用起来蛮舒服的,把WebStorm比得跟驼屎一样.也许是因为我没用习惯吧. 1.安装Nod

【转】Backbone.js学习笔记(二)细说MVC

文章转自: http://segmentfault.com/a/1190000002666658 对于初学backbone.js的同学可以先参考我这篇文章:Backbone.js学习笔记(一) Backbone源码结构 1: (function() { 2: Backbone.Events // 自定义事件 3: Backbone.Model // 模型构造函数和原型扩展 4: Backbone.Collection // 集合构造函数和原型扩展 5: Backbone.Router // 路由

《Java程序性能优化》学习笔记 Ⅰ设计优化

豆瓣读书:http://book.douban.com/subject/19969386/ 第一章 Java性能调优概述 1.性能的参考指标 执行时间: CPU时间: 内存分配: 磁盘吞吐量: 网络吞吐量: 响应时间: 2.木桶定律   系统的最终性能取决于系统中性能表现最差的组件,例如window系统内置的评分就是选取最低分.可能成为系统瓶颈的计算资源如,磁盘I/O,异常,数据库,锁竞争,内存等. 性能优化的几个方面,如设计优化,Java程序优化,并行程序开发及优化,JVM调优,Java性能调

Angular JS 学习笔记

特定领域语言 编译器:遍历DOM来查找和它相关的属性, 分为编译和链接两个阶段, 指令:当关联的HTML结构进入编译阶段时应该执行的操作,可以写在名称里,属性里,css类名里:本质上是函数 稳定的DOM:绑定了数据模型的DOM元素的实例不会在绑定的生命周期发生改变 作用域:用来检测模型的改变和为表达式提供执行上下文的 AngularJS 和其它模板系统不同,它使用的是DOM而不是字符串 指令: 由某个属性.元素名称.css类名出现而导致的行为,或者说是DOM的变化 Filter过滤器:扮演着数据

Node.js学习笔记(3) - 简单的curd

这个算是不算完结的完结吧,前段时间也是看了好久的Node相关的东西,总想着去整理一下,可是当时也没有时间: 现在看来在整理的话,就有些混乱,自己也懒了,就没在整理,只是简单的记录一下 一.demo的简单介绍 这次demo,只涉及到简单的curd操作,用到的数据库是mongo,所以要安装mongo数据库,数据库连接驱动是mongoose: 当然关于mongo的驱动有很多,比如mongous mongoskin等:(详见http://cnodejs.org/topic/4f4ca8e0940ce2e

JS学习笔记-OO疑问之封装

封装是面向对象的基础,今天所要学习的匿名函数与闭包就是为了实现JS的面向对象封装.封装实现.封装变量,提高数据.系统安全性,封装正是面向对象的基础. 匿名函数 即没有名字的函数,其创建方式为 function(){...} 单独存在的匿名函数,无法运行,可通过赋值给变量调用或通过表达式自我执行来实现运行. 1.赋值给变量为一般的函数使用方式 var run = function(){ return '方法运行中'; }; alert(run()); 2.通过表达式自我执行 (function(a