一、可维护性

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. IDE转AHCI

    1.Win + R.输入regedit.进入注冊表编辑器 2.找到HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Msahci.将当中的&qu ...

  2. 优化Webpack构建性能的几点建议

    Webpack 作为目前最流行的前端构建工具之一,在 vue/react 等 Framework 的生态圈中都占据重要地位.在开发现代 Web 应用的过程中,Webpack 和我们的开发过程和发布过程 ...

  3. spring mvc对静态资源的访问

    如果我们的项目使用的是springmvc,在web.xml中会有一段这的配置. <servlet> <servlet-name>springMvc</servlet-na ...

  4. IdentityServer(12)- 使用 ASP.NET Core Identity

    IdentityServer具有非常好的扩展性,其中用户及其数据(包括密码)部分你可以使用任何想要的数据库进行持久化. 如果需要一个新的用户数据库,那么ASP.NET Core Identity是你的 ...

  5. python self

    Python要self的理由 Python的类的方法和普通的函数有一个很明显的区别,在类的方法必须有个额外的第一个参数(self),但在调用这个方法的时候不必为这个参数赋值(显胜于隐的引发). Pyt ...

  6. CentOS 7 学习(三)配置Tomcat集群

    所谓集群,就是把多台服务器集合起来,对外提供一个接口访问,对用户来说完全透明,常用的办法就是前端放一个服务器,将用户请求分发到不同的服务器,大致有以下几种方案 1)采取DNS轮询:将用户的连接解析到不 ...

  7. xcode 没有 iphone4s 模拟器 的解决方法..

    项目需要iphone 4s 测试. 首先是Xcode 8 没有 iphone 4s的模拟器了. 由于线上安装的方式,不管是在code的add simulator 还是 ruby gem 的code-i ...

  8. ABP .Net Core API和Angular前端APP独立部署跨域问题(No Access-Control-Allow-Origin)

    前言: 通过ABP官网(https://aspnetboilerplate.com)下载ASP.NET Core 2.x + Angular模板项目是按ReStful风格架构Web API和angul ...

  9. seo我告诉你

    seo我告诉你,这回seo真的告诉你百度云链接 链接:http://pan.baidu.com/s/1qYpM9y8 密码:mad6 seo优化教程:

  10. BZOJ4817 SDOI2017 相关分析

    4821: [Sdoi2017]相关分析 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special Judge Description Frank对天文 ...