《编写可维护的JavaScript》笔记

基本的格式化

1. 缩进层级

使用制表符进行缩进

每一个缩进层级都用单独的制表符表示(通常一个制表符长度相当于4个字符)

使用空格符进行缩进

每个缩进层级由多个空格字符组成。

2个,4个或8个空格表示一个缩进。

2.语句结尾

JavaScript的语句要么独占一行,要么以分号结尾。

3.行的长度

可将行长度限定在80个字符。

4.换行

当一行长度达到了单行最大字符数限制时,就需要手动将一行拆成两行。通常我们会在运算符后换行,下一行会增加两个层级的缩进。

例外:当给变量赋值时,第二行的位置应当和赋值运算符保持对齐。
eg.

var result = something + anotherThing + yetAnotherThing +
             somethingElse;

5.空行

有时一段代码的语义和另一段代码不相关,这时就应该使用空行将它们分隔,确保语义有关联的代码展现在一起。

一般可在如下场景中添加空行:

  • 在方法之间
  • 在方法中的局部变量和第一条语句之间
  • 在多行或单行注释之前
  • 在方法内的逻辑片段之间插入空行,提高可读性。

6.命名

小驼峰式大小写:由小写字母开始,后续每个单词首字母都大写。
大驼峰式大小写:由大写字母开始,后续每个单词首字母都大写。
eg.(小驼峰式)

var thisIsMyname;
var anotherVariable;

变量名前缀应当是名词,函数名前缀应当是动词以名词,这样可以让变量和函数区分开来。
eg.

var count=10;
function getName(){
    return myname;
}

为了区分普通的变量和常量,可用大写字母和下划线来命名常量,下划线用以分隔单词。
eg.

var MAX_COUNT=10;

在JavaScript中,构造函数只不过是前面冠以new运算符的函数,用来创建对象。构造函数的命名遵照大驼峰命名法。
构造函数的命名也常常是名词,因为它们是用来创建某个类型的实例的。
eg.

function Person(name) {
    this.name=name;
}

Person.prototype.sayname=function() {
    alert(this.name);
};

var me=new Person("Nicholas");

在以大驼峰命名法命名的函数如果是名词的话,前面一定会有new运算符。

7.直接量

在JavaScript中,字符串可以用双引号括起来,也可以用单引号括起来。

创建多行字符串:使用字符串连接符(+)将字符串分成多份。
eg.

var longString="Here's the story,of a man "+
               "named Brady.";

在JavaScript中的数字类型只有一种。(八进制写法已被弃用)
eg.

//整数
var count=10;

//小数
var price=10.0;
var price=10.00;

//十六进制写法
var num=0xA2;

//科学计数法
var num=1e23;

使用null的情况:

  • 用来初始化一个变量,这个变量可能赋值为一个对象。
var person=null;
  • 用来和一个已经初始化的变量比较,这个变量可以是也可以不是一个对象。
var person=getPerson();
if(person!==null) {
    doSomething();
}
  • 当函数的参数期望是对象时,用作参数传入。
  • 当函数的返回值期望是对象时,用作返回值传出。
 function getPerson() {
     if(condition) {
        return new person("Nicholas");
    } else {
        return null;
    }
}
  • 不要使用null来检测是否传入了某参数。
function doSomething(arg1,arg2,arg3,arg4) {
    if(arg4!=null) {
        doSomethingElse();
    }
}           //不好
  • 不要用null来检测一个未初始化的变量。
var person;
if(person!=null) {
    doSomething();
}

那些没有被初始化的变量都有一个初始值,即undefined,表示这个变量等待被赋值。
尽量避免在代码中使用undefined。可以有效地确保只在一种情况下typeof才会返回“undefined”:当变量未声明时。
typeof运算符运算null的类型时返回“object”。

对象直接量

允许将所有的属性都括在一对花括号内。
eg.

var book= {
    title:"Maintainable JavaScript",
    author:"Nicholas C.Zakas"
};

数组直接量
eg.

var colors=["red","green","blue"];
var numbers=[1,2,3,4];
var numbers = new Array(1,2,3,4);
//不好

注释

1.单行注释

//这是一句单行注释
  • 独占一行的注释,用来解释下一行代码。这行注释之前总是有一个空行,且缩进层级和下一行代码保持一致。
  • 在代码行的尾部的注释。代码结束到注释之间至少有一个缩进。不应超过单行最大字符数限制。
  • 被注释掉的大段代码。

2.多行注释

/*多行
注释*/

/*
 *另一段注释
 *这段注释包含两行文本
 */

出现在将要描述的代码前。

注释前有一个空行,缩进层级与代码一致,星号后有空格。
代码尾部注释不要用多行注释。

3.使用注释

在需要让代码变得更清晰时添加注释。

  • 难于理解的代码
  • 可能被误认为错误的代码
  • 浏览器特性hack
  • 文档注释
    多行注释以/**开始,接下来是描述信息,其中使用@符号来表示一个或多个属性。
  • 所有的方法
  • 所有的构造函数
  • 所有包含文档化方法的对象

语句和表达式

不论块语句包含多行代码还是单行代码,都应当总是使用花括号。
所有的块语句都应使用花括号:

  • if
  • for
  • while
  • do…while
  • try…catch…finally

1.花括号的对齐方式

  • 将左花括号放置在块语句中第一句代码的末尾
if (condition) {
    doSomething();
} else {
    doSomethingElse();
}
  • 将左花括号放置于块语句首行的下一行
if (condition)
{
    doSomething();
}
else
{
    doSomethingElse();
}

2.块语句间隔

在语句名,圆括号,左花括号之间的空格问题。if(
eg.

if(condition){
    doSomething();
}
if (condition) {
    doSomething();
}                      *
if ( condition ) {
    doSomething();
}

3.switch语句

switch语句中可以使用任意类型值,任何表达式都可合法地用于case从句。

缩进

  • 每条case语句相对于switch关键字都缩进一个层级。
    从第二条case语句开始,每条case语句前后各有一个空行。
    eg.
switch (condition) {
    case 1:
        //代码
        break;

    case 1:
        //代码
        break;

    default:
        //代码
}
  • case关键字保持和switch左对齐
    在语句中并没有空行的存在

default

可在没有默认行为且写了注释的情况下省略default。

4.with语句

在严格模式中,with语句是被明确禁止的。
尽量避免使用with语句。

5.for循环

传统的for循环往往用于遍历数组成员

var values=[1,2,3,4,5,6,7],
    i,len;
for(i=0,len=values.length;i<len;i++) {
    process(values[i]);
}

可用break,continue更改循环的执行过程
continue语句可用条件语句代替(尽可能避免使用continue语句)

6.for-in循环

用来遍历对象属性。它不仅遍历对象的实例属性,同样还遍历从原型继承来的属性。所以最好使用hasOwnProperty()方法来为for-in循环过滤出实例属性。

var prop;

for(prop in object) {
    if(object.hasOwnProperty(prop)) {
        console.log("Property name is "+prop);
        console.log("Property value is "+object[prop]);
    }
}

想要找原型链。而不使用hasOwnProperty时,应当补充注释。

变量、函数和运算符

1.变量声明

不论var语句是否真正会被执行,所有的var语句都提前到包含这段逻辑的函数的顶部执行。

function doSomething() {

    var result=10+value;
    var value=10;
    return result;
}

用到变量value时,它的值是一个特殊值undefined,resultde 的值就是NaN(非数字)。在那之后value才最终赋值为10。

在函数内部任意地方定义变量和在函数顶部定义变量是完全一样的。

可将所有的var语句合并为一个语句,每个变量的初始化独占一行。赋值运算符应当对齐。对于那些没有初始值的变量应放在var语句的尾部。
eg.

var value = 10,
   result = value + 10,
   i,
   len;

2.函数声明

和变量声明一样,函数声明也会被JavaScript引擎提前。因此,在代码中函数的调用可以出现在函数声明之前。

推荐先声明函数然后再使用。

函数内部的局部函数应当紧接着变量声明之后声明。

函数声明不应出现在语句块之内。

3.函数调用间隔

推荐:在函数名和左括号之间没有空格。

4.立即调用的函数

JavaScript中允许声明匿名函数(本身没有命名的函数),并将匿名函数赋值给变量或者属性。
为了让立即执行的函数被一眼看出来,可以将函数用一对圆括号包裹起来。

var value=(function() {
    //函数体

    return {
        message:"Hi"
    }
}());

5.严格模式

通过使用如下指令脚本以严格模式执行。

"use strict";

这条编译指令不仅用于全局,也适用于局部。但是最好不要在全局作用域中使用“use strict”

function doSomething() {
    "use strict";
    //代码
}

6.相等

当要比较的两个值的类型不同时,==和!=这两个运算符都会有强制类型转换。

  • 将数字和字符串进行比较,字符串会首先转换为数字,然后执行比较。
  • 一个布尔值和数字比较,布尔值会首先转换为数字,然后进行比较。false值变为0,true变为1.
  • 如果其中一个值是对象而另一个不是,则会首先调用对象的valueOf()方法,得到原始类型值再进行比较。如果没有定义valueOf(),则调用toString()。
  • null和undefined这两个特殊值被认为是相等的。

由于强制类型转换的缘故,我们应当使用===和!==。比较不会涉及强制类型转换。

编写维护JavaScript》向开发人员阐述了如何在团队开发中编写具备高可维护性的JavaScript代码,书中详细说明了作为团队一分子,应该怎么写JavaScript。本书内容涵盖了编码风格、编程技巧、自动化、测试等几方面,既包括具体风格和原则的介绍,也包括示例和技巧说明,最后还介绍了如何通过自动化的工具和方法来实现一致的编程风格。   《编写维护JavaScript》作者Nicholas C. Zakas是顶级的Web技术专家,也是《JavaScript高级程序设计》一书的作者。他曾是Yahoo!的首席前端开发工程师,在完成了从一名“独行侠”到“团队精英”的蜕变后,他站在前端工程师的角度提炼出众多的最佳编程实践,其中包括很多业内权威所推崇的最佳法则,而这些宝贵经验正是本书的核心内容。   《编写维护JavaScript》适合前端开发工程师、JavaScript程序员和学习JavaScript编程的读者阅读,也适合开发团队负责人、项目负责人阅读。运用本书中讲述的技巧和技术,可以使JavaScript团队编程从侠义的个人偏好的阴霾走出来,走向真正的高可维护性、高效能和高水准。 第一部分 编程风格 第1章 基本的格式化 1.1 缩进层级 1.2 语句结尾 1.3 行的长度 1.4 换行 1.5 空行 1.6 命名 1.6.1 变量和函数 1.6.2 常量 1.6.3 构造函数 1.7 直接量 1.7.1 字符串 1.7.2 数字 1.7.3 null 1.7.4 undefined 1.7.5 对象直接量 1.7.6 数组直接量 第2章 注释 2.1 单行注释 2.2 多行注释 2.3 使用注释 2.3.1 难于理解的代码 2.3.2 可能被误认为错误的代码 2.3.3 浏览器特性hack 2.4 文档注释 第3章 语句和表达式 3.1 花括号的对齐方式 3.2 块语句间隔 3.3 switch语句 3.3.1 缩进 3.3.2 case语句的“连续执行” 3.3.3 default 3.4 with语句 3.5 for循环 3.6 for-in循环 第4章 变量、函数和运算符 4.1 变量声明 4.2 函数声明 4.3 函数调用间隔 4.4 立即调用的函数 4.5 严格模式 4.6 相等 4.6.1 eval() 4.6.2 原始包装类型 第二部分 编程实践 第5章 UI层的松耦合 5.1 什么是松耦合 5.2 将JavaScript从CSS中抽离 5.3 将CSS从JavaScript中抽离 5.4 将JavaScript从HTML中抽离 5.5 将HTML从JavaScript中抽离 5.5.1 方法1:从服务器加载 5.5.2 方法2:简单客户端模板 5.5.3 方法3:复杂客户端模板 第6章 避免使用全局变量 6.1 全局变量带来的问题 6.1.1 命名冲突 6.1.2 代码的脆弱性 6.1.3 难以测试 6.2 意外的全局变量 避免意外的全局变量 6.3 单全局变量方式 6.3.1 命名空间 6.3.2 模块 6.4 零全局变量 第7章 事件处理 7.1 典型用法 7.2 规则1:隔离应用逻辑 7.3 规则2:不要分发事件对象 第8章 避免“空比较” 8.1 检测原始值 8.2 检测引用值 8.2.1 检测函数 8.2.2 检测数组 8.3 检测属性 第9章 将配置数据从代码中分离出来 9.1 什么是配置数据 9.2 抽离配置数据 9.3 保存配置数据 第10章 抛出自定义错误 10.1 错误的本质 10.2 在JavaScript中抛出错误 10.3 抛出错误的好处 10.4 何时抛出错误 10.5 try-catch语句 10.6 错误类型 第11章 不是你的对象不要动 11.1 什么是你的 11.2 原则 11.2.1 不覆盖方法 11.2.2 不新增方法 11.2.3 不删除方法 11.3 更好的途径 11.3.1 基于对象的继承 11.3.2 基于类型的继承 11.3.3 门面模式 11.4 关于Polyfill的注解 11.5 阻止修改 第12章 浏览器嗅探 12.1 User-Agent检测 12.2 特性检测 12.3 避免特性推断 12.4 避免浏览器推断 12.5 应当如何取舍 第三部分 自动化 第13章 文件和目录结构 13.1 最佳实践 13.2 基本结构 第14章 Ant 14.1 安装 14.2 配置文件 14.3 执行构建 14.4 目标操作的依赖 14.5 属性 14.6 Buildr项目 第15章 校验 15.1 查找文件 15.2 任务 15.3 增强的目标操作 15.4 其他方面的改进 15.5 Buildr任务 第16章 文件合并和加工 16.1 任务 16.2 行尾结束符 16.3 文件头和文件尾 16.4 加工文件 第17章 文件精简和压缩 17.1 文件精简 17.1.1 使用YUI Compressor精简代码 17.1.2 用Closure Compiler精简 17.1.3 使用UglifyJS精简 17.2 压缩 17.2.1 运行时压缩 17.2.2 构建时压缩 第18章 文档化 18.1 JSDoc Toolkit 18.2 YUI Doc 第19章 自动化测试 19.1 YUI Test Selenium引擎 19.1.1 配置一台Selenium服务器 19.1.2 配置YUI Test Selenium引擎 19.1.3 使用YUI Test Selenium引擎 19.1.4 Ant的配置写法 19.2 Yeti 19.3 PhantomJS 19.3.1 安装及使用 19.3.2 Ant的配置写法 19.4 JsTestDriver 19.4.1 安装及使用 19.4.2 Ant的配置写法 第20章 组装到一起 20.1 被忽略的细节 20.2 编制打包计划 20.2.1 开发版本的构建 20.2.2 集成版本的构建 20.2.3 发布版本的构建 20.3 使用CI系统 20.3.1 Jenkins 20.3.2 其他CI系统 附录A JavaScript编码风格指南 附录B JavaScript工具集
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值