27 Feb 2017 09:46 +0000

Author: Nicholas C. Zakas

编程风格

编程风格 (style guideline) 用来规约单文件代码的规划. 编程风格是编码规范 (code convention) 的一种. 在编程风格外, 编码规范还包括编程最佳实践, 文件和目录的规划及注释等方面.

例举几个可供参考的编程风格指南:

Code Conventions for the JavaScript Programming Language - Douglas Crockford

Google JavaScript Style Guide

Dojo Style Guide

JavaScript Style Guide | jQuery

第 1 章, 基本格式化

缩进层级

制表符缩进和空格缩进之争历来已久. 二者均有各自优劣, 具体的选择取决于团队偏好, 不应纠结于某一种缩进. 只要牢记一点: 不要在团队中将二者混用.

语句结尾

养成在语句结尾插入分号的习惯. 得益于分析器的自动分号插入 (Automatic Semicolon Insertion, ASI) 机制, 省略 JavaScript 代码的语句结束分号不影响代码正常工作, 但出于几点原因, 不推荐这么做.

行长度

一行代码过长将导致窗口出现横向滚动条, 经典的建议是将行长度保持在 80 字符以内. (指英文字符, 中文字符算两个)

换行

如果约定将行长度保持在一定长度之内, 就涉及 (在一个语句内) 换行的问题. 建议的做法: 在运算符后换行, 并在新行添加两层缩进, 即

// 推荐
callAFunction(document, element, window, "some string value", true, 123,
        navigator);

// 不推荐
callAFunction(document, element, window, "some string value", true, 123,
    navigator);

// 不推荐
callAFunction(document, element, window, "some string value", true, 123
        , navigator);

采用两层缩进可以区别于正常缩进, 例如:

if (isLeapYear && isFebruary && day == 28 && itsYourBirthday &&
        noPlans) {

    waitAnotherFourYears();
}

以上代码中 if 条件语句被拆分为两行, 但 if 语句主体仍是一层缩进, 避免了二者的混淆.

这个规则有一个例外: 在给变量赋值时, 应使第二行与赋值运算符对齐, 即

let result  = something + anotherThing + yetAnotherThing + somethingElse + 
              anotherSomethingElse;

空行

如果没有特殊爱好, 可以遵从以下空行条件:

  • 在方法之间
  • 在方法中的局部变量和第一条语句之间
  • 在多行或单行注释之前
  • 在方法内的逻辑片断之间

命名

主流的变量命名法有蛇式 (snake case) , 小驼峰式 (camel case) , 大驼峰式 (pascal case) 等, 大多数标准中推荐使用小驼峰式命名法, 即变量名以小写字母开头, 后续每个单词首字母都大写.

// snake case
let this_is_my_name;

// camel case
let thisIsMyName

// pascal case
let ThisIsMyName
变量与函数

几个要点:

  • 命名长度尽可能短, 以足够表示其作用为准
  • 尽量在变量名中体现出值的数据类型, 如count, length, code, name, message
  • 避免无意义的命名, 如foo, bar等, 不过i, j, k等单字符例外, 它们常用于循环中
  • 可以用动词 (如can, has, is, get, set) 将函数名与变量名区分开, 如isEnabled是一个函数, myName是一个变量
常量

全大写字母加下划线的常量名是很多语言通行的做法. 如MAX_COUNT.

构造函数

和常量一样, 使用大驼峰式 (pascal case) 构造函数名是很多语言通行的做法. 如ButtonComponent.

JavaScript 的构造函数就是面向对象的类, JavaScript 本身没有class语法

直接量

字符串

JavaScript 中, 用单引号和双引号括起的字符串在功能上完全相同. 只要在团队中保持同一种风格, 并没有什么要担心的.

使用单引号不符合 ECMA-404 (JSON) 规范, 因此如果没有什么特殊偏好, 还是建议采用双引号, 参见 String - MDN.

在定义过长的, 需要换行的字符串时, 建议把字符串拆成两部分, 并用 "+" 号将它们连接起来:

let longString = 'Here\'s the story=, of a man ' +
                 'named Brady.';
数字

建议在定义数字时:

  • 小数不要省略小数部分 (如1.0不要写成1.)
  • 小数不要省略整数部分 (如0.1不要写成.1)
  • 不要在数字前加 0 , 八进制写法已经被弃用了
null

建议将且仅将 null 用于以下情况:

  • 初始化一个可能被赋值为一个对象的变量
  • 用于和一个已经初始化的变量进行比较
  • 当函数期望传入对象时, 作参数传入
  • 当函数期望返回对象时, 作返回值传出

不要将 null 用于以下情况:

  • 不要用 null 来检测是否传入了某个参数
  • 不要用 null 来检测一个未初始化的变量
// ok
let person = null;

// ok
function getPerson() {
    if (condition) {
        return new Person('Ncholas');
    } else {
        return null;
    }
}

// ok
let person - getPerson();
if (person !== null) {
    doSomething();
}

// 不要用 null 来检测是否传入了某个参数
function doSomething(arg1, arg2, arg3, arg4) {
    if (arg4 != null) {
        doSomethingElse(); 
    }
}

// 不要用 null 来检测一个未初始化的变量
let person;
if (person != null) {
    doSomething();
}

null == undefined是真, 而null === undefined是假

undefined

声明而未初始化的变量会有一个初始值, 即 undefined. JavaScript 有一个奇怪的行为, 用 typeof 检测一个未声明的变量和一个声明而未初始化的变量都会返回 undefined (实际上未声明和声明但未初始化的变量有着天壤之别) , 因此, 推荐强制规定变量必须初始化, 即:


let foo;
let bar = null;

console.log(typeof foo); // undefined, 不推荐, 与未声明的 foobar 相混淆
console.log(typeof bar); // object, 推荐, 给所有声明的变量赋予初始值 null, typeof 返回 object
console.log(typeof foobar); // undefined

console.log(foo == 1); // false
console.log(bar == 1); // false
console.log(foobar == 1); // error!
对象直接量

通常用对象直接量的做法创建对象:

// 不推荐
let book = new Object();
book.title = 'Maintainable Javascript';
book.author = 'Nicholas C. Zakas';

// 通常用对象直接量定义对象
let book = {
    title: 'Maintainable JavaScript',
    author: 'Nicholas C. Zakas'
};
数组直接量

与对象直接量类似:

// 不推荐
let colors = new Array('red', 'green', 'blue');

// 通常用数组直接量定义数组
let colors = ['red', 'green', 'blue'];

Loading comments...