一.可维护性优化

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模块

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

  1. JS学习笔记5_DOM

    1.DOM节点的常用属性(所有节点都支持) nodeType:元素1,属性2,文本3 nodeName:元素标签名的大写形式 nodeValue:元素节点为null,文本节点为文本内容,属性节点为属性 ...

  2. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  3. Vue.js学习笔记(2)vue-router

    vue中vue-router的使用:

  4. JS 学习笔记--9---变量-作用域-内存相关

    JS 中变量和其它语言中变量最大的区别就是,JS 是松散型语言,决定了它只是在某一个特定时间保存某一特定的值的一个名字而已.由于在定义变量的时候不需要显示规定必须保存某种类型的值,故变量的值以及保存的 ...

  5. WebGL three.js学习笔记 使用粒子系统模拟时空隧道(虫洞)

    WebGL three.js学习笔记 使用粒子系统模拟时空隧道 本例的运行结果如图: 时空隧道demo演示 Demo地址:https://nsytsqdtn.github.io/demo/sprite ...

  6. WebGL three.js学习笔记 法向量网格材质MeshNormalMaterial的介绍和创建360度全景天空盒的方法

    WebGL学习----Three.js学习笔记(5) 点击查看demo演示 Demo地址:https://nsytsqdtn.github.io/demo/360/360 简单网格材质 MeshNor ...

  7. WebGL three.js学习笔记 创建three.js代码的基本框架

    WebGL学习----Three.js学习笔记(1) webgl介绍 WebGL是一种3D绘图协议,它把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的 ...

  8. vue.js 学习笔记3——TypeScript

    目录 vue.js 学习笔记3--TypeScript 工具 基础类型 数组 元组 枚举 字面量 接口 类类型 类类型要素 函数 函数参数 this对象和类型 重载 迭代器 Symbol.iterat ...

  9. 2019-4-29 js学习笔记

    js学习笔记一:js数据类型   1:基本数据类型       number类型(整数,小数)      String类型          boolean类型        NaN类型其实是一个nu ...

随机推荐

  1. 种类并查集(POJ 1703)

    1703 -- Find them, Catch them http://poj.org/problem?id=1703 题目大意:有2个敌对帮派,输入D a b表示a,b在不同帮派,输入A a b表 ...

  2. B-F 字符串匹配算法

    Brute-Froce 算法是串的匹配模式算法中的一种其匹配方式如下: 1.设有字符串 a ,b;a为主串,在 a 中查找 b 串的位置 2.匹配方式如下: 2.1: 分别从 a,b串的第一个元素开始 ...

  3. Visual Studio 换皮肤

    通过字体和颜色修改 Visual Studio 提供了修改配色的入口,你完全可以根据自己的喜好进行自定义,下面就通过该方法把编辑器背景设置成 “豆沙绿”. 选择 工具 / 选项 / 环境 / 字体和颜 ...

  4. eval 函数的应用 (去除包装在列表外面的引号)

    a="[u'ANDROID-5a9ac5c22ad94e26b2fa24e296787a35', u'0', 0, 0, 0, 1]" 此时的a是一个字符串,目的是要去掉a上面的引 ...

  5. 未能加载文件或程序集Microsoft.ReportViewer.WebForms, Version=10.0.0.0

    解决方案如下ASP.NET项目使用VS2010开发,部署到windows 2008环境中,出现未能加载文件或程序集“Microsoft.ReportViewer.WebForms, Version=1 ...

  6. ORACLE 数据块dump

    1. rdba(Tablespace relative database block address) 是相对数据块地址,是数据所在的地址,rdba可就是rowid 中rfile#+block#. 根 ...

  7. ORACLE rowid切分大表

    通过如下sql获取rowid切分范围 ) || dbms_rowid.rowid_create(, DOI, lo_fno, lo_block, ) ) || ) || dbms_rowid.rowi ...

  8. Spring----->projects----->Spring Web Flow

    1.概述(about Spring Web Folw) Spring Web Flow是spring社区一个子project Spring Web Flow builds on Spring MVC ...

  9. SQL Server Profiler使用方法

    一.SQL Server Profiler使用方法 1.单击开始--程序--Microsoft SQL Server 2005--性能工具--SQL Server Profiler,如下图:   2. ...

  10. hdu4738 Caocao's Bridges

    http://acm.hdu.edu.cn/showproblem.php?pid=4738 题目大意:曹操赤壁之战大败,于是卷土重来.为了避免水上作战,他在长江上建立了一些岛屿,这样他的士兵就可以在 ...