一.可维护性优化

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. iframe的用法

    iframe 元素会创建包含另外一个文档的内联框架(即行内框架). 属性: 创建内联框架(JSP页面) <%@ page language="java" import=&qu ...

  2. 基于PHP生成静态页的实现方法

    t1.php 复制代码 代码如下: <?php// 方法一根据模版生成静态页面// replaceTemplateString函数用于替换模板中指定字符串function replaceTemp ...

  3. Python 单例

    方法1: 1 class Singleton(object): def __new__(cls, *args, **kwargs): if '_inst' not in vars(cls): cls. ...

  4. 使用网易ubuntu镜像加速软件包安装

    用vi工具编辑文件 sudo vi /etc/apt/sources.list 以trusty(14.04)为例,插入下面内容到文件的最前面: deb http://mirrors.163.com/u ...

  5. The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProv

    在mybatis配置文件config.xml中报错: The content of element type "configuration" must match "(p ...

  6. weblogic myeclipse小知识

    新建域 http://jingyan.baidu.com/article/f7ff0bfc72904e2e27bb136f.html svn 上down下来一些新项目的时候没法添加到weblogic ...

  7. 自已实现的async 只实现了一部分功能

    不得不说,人和人的技术确实有差距,同样的功能,其他人就是有办写写的更优雅性能更好 不论是C还是js 自已有功能但看着也比人家的丑好多. //最终效果 同async //目前实现了个人最常用的 seri ...

  8. 第五章 springboot + mybatis

    springboot集成了springJDBC与JPA,但是没有集成mybatis,所以想要使用mybatis就要自己去集成.集成方式相当简单. 1.项目结构 2.pom.xml <!-- 与数 ...

  9. 遇到的check the manual that corresponds to your MySQL server version for the right syntax错误

    遇到的check the manual that corresponds to your MySQL server version for the right syntax错误. 结果发现是SQL关键 ...

  10. 《Java程序设计》实验5

    20145318 <Java程序设计>实验5 实验内容 运行下载的TCP代码,结对进行,一人服务器,一人客户端: 利用加解密代码包,编译运行代码,一人加密,一人解密: 集成代码,一人加密后 ...