一、可维护性

1 什么是可维护的代码

  • 可理解性——其他人可以接受代码并理解它的意图和一般途径,而无需原开发人员的完整解释。
  • 直观性——代码中的东西一看就能明白,不管其操作过程多么复杂。
  • 可适应性——代码以一种数据上的变化不要求完全重写的方法撰述。
  • 可扩展性——在代码架构上已考虑到在未来允许对核心功能进行扩展。
  • 可调试性——当有地方出错时,代码可以给予你足够的信息来尽可能直接地确定问题所在。

2 代码约定

1)可读性

可读性与代码作为文本文件的格式化方式有关。可读性的大部分内容都是和代码的缩进相关。可读性的另一方面是注释。

2)变量和函数命名

3)变量类型透明

3 松散耦合

1)解耦HTML/JavaScript

HTML呈现应该尽可能与JavaScript保持分离。当JavaScript用于插入数据时,尽量不要直接插入标记。一般可以在页面中直接包含并隐藏标记,然后等到整个页面渲染好之后,就可以用JavaScript显示该标记,而非生成它。另一种方法是进行Ajax请求并获取更多要显示的HTML,这个方法可以让同样的渲染层来输出标记,而不是直接嵌在JavaScript中。

2)解耦CSS/JavaScript

JavaScript只通过动态更改样式类而非特定样式。

3)解耦应用逻辑/事件处理程序

将应用逻辑和事件处理程序相分离,这样两者分别处理各自的东西。一个事件处理程序应该从事件对象中提取相关信息,并将这些信息传送到处理应用逻辑的某个方法中。

一下是要牢记的应用和业务逻辑之间松散耦合的几条原则:

  • 勿将event对象传给其它方法;只传来自event对象中所需的数据;
  • 任何可以在应用层面的动作都应该可以在不执行任何事件处理程序的情况下进行;
  • 任何事件处理程序都应该处理事件,然后将处理转交给应用逻辑。

4 编程实践

1 尊重对象所有权

  • 不要为实例或原型添加属性
  • 避免全局量
  • 避免与null进行比较
  • 使用常量

二、性能

1 注意作用域

1)避免全局查找

可能优化脚本性能最重要的就是注意全局查找。使用全局变量和函数肯定要比局部的开销更大,因为要设计作用域链上的查找。

糟糕的例子:

function updateUI() {
    var imgs = document.getElementByTagName("img");
    for(var i = 0, len = imgs.length; i < len; i++) {
        imgs[i].title = document.title + " image" + i;
    }
    var msg = document.getElementById("msg");
    msg.innerHTML = "Update complete.";
}

改为:

function updateUI() {
    var doc = document;
    var imgs = doc.getElementsByTagName("img");
    for(var i = 0, len = imgs.length; i < len; i++) {
        imgs[i].title = doc.title + " image " + i;
    }
    var msg = doc.getElementById("msg");
    msg.innerHTML = "Update complete";
}

2)避免with语句

with语句会创建自己的作用域,一次会增加其中执行的代码的作用域链的长度。由于额外的作用域链查找,在with语句中执行的代码肯定会比外面执行的代码要慢。

2 选择正确方法

1)避免不必要的属性查找

使用变量和数组要比访问对象上的属性更有效率,后者是一个O(n)操作。对象上的任何属性查找都要比访问变量或者数组花费更长的时间,因此必须在原型链中对拥有该名称的属性进行一次搜索。简而言之,属性查找越多,执行时间就越长。

尽可能多地使用局部变量将属性查找替换为值查找。

2)优化循环

3)展开循环

4)避免双重解释

当JavaScript代码想解析JavaScript的时候就会存在双重解释惩罚。当使用eval()函数或者是Function构造函数以及使用setTimeout()传入一个字符串参数时都会发生这种情况。因为代码时包含在字符串中,不能在初始的解析过程中完成,也就是说在JavaScript代码运行的同事必须新启动一个解析器来解析新的代码。实例化一个新的解析器有不容忽视的开销,所以这种代码要比直接解析慢的多。

5)性能的其他注意事项

  • 原生方法较快
  • Switch语句较快
  • 位运算符较快

三、最小化语句数

1 多个变量声明

2 插入迭代值

当使用迭代值(也就是在不同的位置进行增加或较少的值)的时候,尽可能合并语句。

3 使用数组和对象字面量

两种创建数组和对象的方法:使用构造函数或者是使用字面量。使用构造函数总是要用到很多的语句来插入元素或者定义属性,而字面量可以将这些操作在一个语句中完成。

四、优化DOM交互

1 最小化现场更新

一旦你需要访问的DOM部分是已经显示的页面的一部分,那么你就是在进行一个现场更新。之所以叫现场更新,是因为需要立即(现场)对页面对用户的显示进行更新。每一个更改,不管是插入单个字符,还是移除整个片段,都有一个性能惩罚,因为浏览器要重新计算无数尺寸以进行更新。现场更新进行得越多,代码完成执行所花的时间就越长;完成一个操作所需的现场更新越少,代码就越快。

糟糕的例子:

var list = document.getElementById("myList"),
    item,
    i;
for(i = 0; i < 10; i++) {
    item = document.createElement("li");
    list.appendChild(item);
    item.appendChild(document.createTextNode("Item " + i));
}

更改:

var list = document.getElementById("myList"),
    fragment = document.createDocumentFragment(),
    item,
    i;
for(i = 0; i < 10; i++) {
    item = document.createElement("li");
    fragment.appendChild(item);
    item.appendChild(document.createTextNode("Item " + i));
}
list.appendChild(fragment);

2 使用innerHTML

有两种在页面上创建DOM节点的方法:使用诸如createElement()和appendChild()之类的DOM方法,以及使用innerHTML。对于小的DOM更改而言,两种方法效率都差不多。然而,对于大的DOM更改,使用innerHTML要比使用标准DOM方法创建同样的DOM结构快的多。

当把innerHTML设置为某个值时,后台会创建一个HTML解析器,然后使用内部的DOM调用来创建DOM结构,而非基于JavaScript的DOM调用。由于内部方法是编译好的而非解释执行的,所以执行快得多。

前面的例子还可以用innerHTML改写如下:

var list = document.getElementById("myList");
    html = "",
    i;
for(i = 0; i < 10; i++) {
    html += "<li>Item " + i + "</li>";
}
list.innerHTML = html;

3 使用事件代理

页面上的事件处理程序的数量和页面相应用户交互的速度之间有个负相关。为了减轻这种惩罚,最好使用事件代理。

4 注意HTMLCollection

任何时候要访问HTMLCollection,不管它是一个属性还是一个方法,都是在文档上进行一个查询,这个查询开销很昂贵。最小化访问HTMLCollection的次数可以极大地改进脚本的性能。

三、部署

1 构建过程

写的代码不应该原封不动地放入浏览器中,理由如下。

  • 知识产权问题——如果把带有完整注释的代码放到线上,那别人就更容易知道你的意图,对它再利用,并且可能找到安全漏洞。
  • 文件大小——书写代码要保证容易阅读,才能更好地维护,但是这对性能是不利的。浏览器并不能从额外的空白字符或者冗长的函数名和变量名中获得什么好处。
  • 代码组织——组织代码要考虑到可维护性并不一定是传送给浏览器的最好方式。

推荐Web应用中尽可能使用最少的JavaScript文件,是因为HTTP请求是Web中的主要性能瓶颈之一。记住通过<script>标记引用JavaScript文件是一个阻塞操作,当代码下载并运行的时候会停止其他所有的下载。因此,尽量从逻辑上将JavaScript代码分组成部署文件。

2 验证

3 压缩

当谈及JavaScript文件压缩,其实在谈论两个东西:代码长度和配重(Wire weight)。代码长度指的是浏览器所需解析的字节数,配重指的是实际从服务器传送到浏览器的字节数。

1)文件压缩

压缩器一般进行如下一些步骤:

  • 删除额外的空白(包括换行);
  • 删除所有注释;
  • 缩短变量名。

2)HTTP压缩

配重指的是实际从服务器传送到浏览器的字节数。因为现在的服务器和浏览器都具有压缩功能,这个字节数不一定和代码长度一样。

[笔记]《JavaScript高级程序设计》- 最佳实践的更多相关文章

  1. 24. javacript高级程序设计-最佳实践

    1. 最佳实践 l 来自其他语言的代码约定可以用于决定何时进行注释,以及如何进行缩进,不过JavaScript需要针对其松散类型的性质创造一些特殊的约定 l javascript应该定义行为,html ...

  2. 读书笔记-JavaScript高级程序设计(1)

    1.组合继承 (JavaScript 中最常用的继承模式 ) (position: page168) (书中定义了两个变量名 SuperType   SubType  乍一看 感觉不太能区分,我将改为 ...

  3. 读书笔记 - javascript 高级程序设计 - 第二章 在Html中使用JavaScript

    1 <script>的6个属性 async  立即下载当前script标签的外部脚本 但不能影响别的 charset 没用了 defer  文档显示之后再执行脚本,只对外部脚本有效 lan ...

  4. 读书笔记 - javascript 高级程序设计 - 第一章 简介

      第一章 简介   诞生时间 1995 最初用途 客服端验证 第一版标准 注意是标准 1997年 Ecma-262  一个完整的js实现由三部分组成 ECMAScript DOM 文档对象模型 BO ...

  5. 《JavaScript高级程序设计》学习笔记12篇

    写在前面: 这12篇博文不是给人看的,而是用来查的,忘记了什么基础知识,点开页面Ctrl + F关键字就好了 P.S.如果在对应分类里没有找到,麻烦告诉我,以便尽快添上.当然,我也会时不时地添点遗漏的 ...

  6. 《JavaScript高级程序设计(第3版)》笔记-序

    很少看书,不喜欢看书,主要是上学时总坐不住,没有多大定性,一本书可以两天看完,随便翻翻,也可以丢在角落里几个月不去动一下. 上次碰到了<JavaScript高级程序设计(第3版)>感觉真的 ...

  7. 【javascript学习——《javascript高级程序设计》笔记】DOM操作

    DOM(文档对象模型)是针对HTML和XML文档的一个API(应用程序编程接口).DOM描绘了一个层次节点树,允许开发人员添加.移除和修改. 1.节点层次 <html> <head& ...

  8. 《JavaScript高级程序设计》读书笔记--前言

    起因 web编程过程使用javascript时感觉很吃力,效率很低.根本原因在于对javascript整个知识体系不熟,看来需要找些书脑补一下,同时欢迎众网友监督. 大神推荐书籍 看了博客大神们推荐的 ...

  9. 《JavaScript高级程序设计》学习笔记(3)——变量、作用域和内存问题

    欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 本节内容对应<JavaScript高级程序设计>的第四章内容. 1.函数:通过函数可以封装 ...

  10. javascript高级程序设计阅读笔记(一)

    javascript高级程序设计阅读笔记(一) 工作之余开发些web应用作为兴趣,在交互方面需要掌握javascript和css.HTML5等技术,因此读书笔记是必要的. javascript简介 J ...

随机推荐

  1. String内存溢出异常(错误)可能的原因及解决方式

    摘要:本Blog主要为了阐述java.lang.OutOfMemoryError:PermGenspace可能产生的原因及解决方式. 当中PermGen space是Permanent Generat ...

  2. 在Laravel中使用swoole来取代nginx作为http服务器

    1.是什么限制Laravel框架的速度? Laravel框架启动的时候需要加载很多文件,再加上其出了名的生态环境好,所以在开发过程中我们就会发现有非常多的已经造好的轮子,这也就使得Laravel的一次 ...

  3. JAVA入门[7]-Mybatis generator(MBG)自动生成mybatis代码

    一.新建测试项目 新建Maven项目MybatisDemo2,修改pom.xml引入依赖.dependencies在上节基础上新增 <dependency> <groupId> ...

  4. @Autowired注解在抽象类中实效的原因分析

    最近在工作中遇到这个问题,在抽象类中使用Autowired这个注解,注入mybatis的dao时,总是出现空指针异常,通过日志的打印,发现是这个dao注入失败为空.然后通过new出spring上下文对 ...

  5. AOP入门(转)

    本文转自http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html Aspect Oriented Programming  面向切 ...

  6. spring boot + druid + 封装JdbcTemplate

    本源码内容如下: spring boot项目 用的druid连接池 druid监控页面配置 数据操作用spring jdbctemplate 进一步封装spring jdbctemplate支持用对象 ...

  7. NYOJ915——+-字符串

    +-字符串 时间限制:1000 ms  |  内存限制:65535 KB 难度:1   描述 Shiva得到了两个只有加号和减号的字符串,字串长度相同.Shiva一次可以把一个加号和它相邻的减号交换. ...

  8. Kotlin——最详细的常量、变量、注释的使用

    在Kotlin中的变量.常量以及注释多多少少和Java语言是有着不同之处的.不管是变量.常量的定义方式,还是注释的使用.下面详细的介绍Kotlin中的变量.常量.注释的使用.以及和Java的对比. 如 ...

  9. c语言库函数测试

    1.函数名: abort功  能: 异常终止一个进程用  法: void abort(void);程序例: #include <stdio.h> #include <stdlib.h ...

  10. 从头开始搭建一个Spring boot+ActiveMQ高可用分布式环境

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...