Serenader

Learning by sharing.

JavaScript Coding Style

其实在很久之前就一直想写这个 Coding style 了,只是一直懒得写出来。最近在公司和搭档一起写项目的时候才深刻的感受到,统一一下 Coding Style 是多么的重要。和她一起复习了一下一些常见的 Coding style ,过后我觉得还是非常有必要将这个写出来,作为自己的一个规范,以后就一直沿用这种规范好了。

声明:此规范仅仅是个人的使用习惯,不具有代表性。如果有更好的建议欢迎提出。

这篇文章写于2014年的8月份,截至现在(2016年8月)我自己的编程习惯已经有了很大的改变。因此文章的内容并不能反映我目前的编码偏好,各位看官当做参考即可。

目前而言我主要使用 Airbnb 的规范,并且配合 Eslint 来做代码风格和质量检查。

空格以及 Tab

永远使用软 Tab (Soft Tab) 作为缩进。

使用 4 个空格代替一个 Tab 。所以在代码里面的缩进应该是 4 个空格,而不应该有 2 个空格或者有 Tab 符。

在使用编辑器进行编码的时候,一开始就应该先设置 Tab 键的行为。

单引号双引号

使用单引号或双引号没有区别。但是唯一需要注意的是,在同一个项目里面必须统一使用一种引号。

优先选择单引号。

分号

表达式语句结束前必须有分号。

//必须添加分号的
var foo = 'bar';

var foo = function () {
	// some codes
};

someFunc(arg);

// 不用添加分号的

function foo () {

}

if (true) {

} else {

}

while () {

}

var i = 0,
	l = arr.length;
    
for (; i < l; i++) {

}

使用驼峰式命名规范

变量的命名应该使用驼峰式命名规范。而对于某些项目的一些私有变量,则可以在变量名前加一个 _

var nameSpace = 'foo';


var Super = function () {
	this._v = '0.1';
};


变量声明

  • 永远使用 var 进行变量声明。
// 不好的声明

foo = 'a'; // 没有声明过的变量直接使用会产生全局变量污染,不推荐。


// 正确的声明

var foo = 'a';
  • 使用单一 var

在有多个变量需要声明的时候,应该使用单一的 var 进行声明。这样好处是便于阅读而且可以节省一些字节。不过坏处就是容易出错。特别是容易将 , 打成 ; 。这一点需要特别注意。

// 不推荐的写法
var foo;
var bar;
var a = 1;
var b = 'a';

// 推荐的写法
var foo,
    bar,
    a = 1,
    b = a;

另外还有一个地方需要注意的是,使用单一 var 进行声明时,每一个变量占用一行。换行的时候应该与 var 缩进一个 Soft Tab 。也就是 4 个空格。具体效果如上所示。

  • 等号左右的空白

等号左右两端应该留有一个空格。这样会使得看起来更清晰,可读性更高。

// 不好的写法

var foo='bar';

// 推荐的写法

var foo = 'bar';
  • 使用字面量对象声明对象和数组

如无特殊情况,使用字面量标识:

var obj = {},
	arr = [];
  • 变量声明的位置

变量的声明必须放在当前作用域的最顶端。

// 不好的写法

function fn () {
	// 在变量声明之前有语句

	var a = 'a',
    	b = 'b';
}

// 好的写法

function fn () {
	var a = 'a',
    	b = 'b';
    
	// 其他语句
}
  • 函数的写法

function 后面的一对括号左右应该有一个空格。目的是为了统一,而且也可以增强可读性。

// 不好的写法

var foo = function(){
	// 内部代码
};

function foo(){
	// 内部代码
}

someFunc(arg,function(){
	//内部代码
});


// 推荐的写法

var foo = function () {
	// 内部代码
}

function foo () {
	// 内部代码
}

someFunc(arg, function () {
	// 内部代码
});


需要注意的是,在执行函数时,当有多个参数需要传递时,参数之间应该有一个空格。如 someFunc(arg1, arg2)

细节

统一使用空格。

// 推荐的写法

if (true) {

} else {

}

while (true) {

}

var i = 0,
	l = arr.length;
    
for (; i < l; i++) {

}

// 传递参数给函数时,推荐的写法

someFunc({
	foo: 'bar' // 传递对象。冒号 : 后面有一个空格
});

someFunc(['foo', 'bar']); // 传递数组。逗号后面有一个空格。

someFunc('string'); // 传递字符串。

类型检测

  • 直接类型:
// string
typeof foo === 'string'

// number
typeof foo === 'number'

// object
typeof foo === 'object'

// boolean
typeof foo === 'boolean'

// arrary
Object.prototype.toString.call(foo) === '[object Array]'

// node
elem.nodeType === 1

// null
foo === null

// null or undefined
foo == null

// 全局变量
typeof foo === 'undefined'

// 局部变量
foo === undefined

// 属性
obj.foo === undefined
obj.hasOwnProperty(foo)
'foo' in obj

强制类型转换

var number = 1,
	string = '1',
    bool = false;
    
number; // 1

number + ''; // '1'

string; // '1'

+string; // 1

+string++; // 1

string; // 2

bool; // false

+bool; // 0

bool + ''; // 'false'
var number = 1,
	string = '1',
    bool = true;
    
string === number; // false

string === number + ''; // true

+string === number; // true

bool === number; // false

+bool === number; //true

bool === string; //false

bool === !!string; //true
var num = 2.5;

parseInt(num, 10);
// 等价于

~~num;

num >> 0;

num >>> 0;
// 结果都是 2 。但是对于负数就有一些不同。

var num = -2.5;

parseInt(num, 10);
// 等价于

~~num;

num >> 0;
// 结果都是 -2;但是

num >>> 0; 
// 结果是 4294967294

对比运算

// 当只是判断一个 array 是否有长度,相对于使用这个:
if ( array.length > 0 ) ...

// ...判断真伪, 请使用这种:
if ( array.length ) ...


// 当只是判断一个 array 是否为空,相对于使用这个:
if ( array.length === 0 ) ...

// ...判断真伪, 请使用这种:
if ( !array.length ) ...


// 当只是判断一个 string 是否为空,相对于使用这个:
if ( string !== "" ) ...

// ...判断真伪, 请使用这种:
if ( string ) ...


// 当只是判断一个 string 是为空,相对于使用这个:
if ( string === "" ) ...

// ...判断真伪, 请使用这种:
if ( !string ) ...


// 当只是判断一个引用是为真,相对于使用这个:
if ( foo === true ) ...

// ...判断只需像你所想,享受内置功能的好处:
if ( foo ) ...


// 当只是判断一个引用是为假,相对于使用这个:
if ( foo === false ) ...

// ...使用叹号将其转换为真
if ( !foo ) ...

// ...需要注意的是:这个将会匹配 0, "", null, undefined, NaN
// 如果你 _必须_ 是布尔类型的 false,请这样用:
if ( foo === false ) ...


// 如果想计算一个引用可能是 null 或者 undefined,但并不是 false, "" 或者 0,
// 相对于使用这个:
if ( foo === null || foo === undefined ) ...

// ...享受 == 类型强制转换的好处,像这样:
if ( foo == null ) ...

// 谨记,使用 == 将会令 `null` 匹配 `null` 和 `undefined`
// 但不是 `false`,"" 或者 0
null == undefined

其他改进

  • 避免使用 switch
// switch 语句示例

switch( foo ) {
  case "alpha":
    alpha();
    break;
  case "beta":
    beta();
    break;
  default:
    // 默认分支
    break;
}


// 一个可支持组合、重用的方法是使用一个对象来存储 “cases”,
// 使用一个 function 来做委派:

var cases, delegator;

// 返回值仅作说明用
cases = {
  alpha: function() {
    // 语句
    // 一个返回值
    return [ "Alpha", arguments.length ];
  },
  beta: function() {
    // 语句
    // 一个返回值
    return [ "Beta", arguments.length ];
  },
  _default: function() {
    // 语句
    // 一个返回值
    return [ "Default", arguments.length ];
  }
};

delegator = function() {
  var args, key, delegate;

  // 把 `argument` 转换成数组
  args = [].slice.call( arguments );

  // 从 `argument` 中抽出最前一个值
  key = args.shift();

  // 调用默认分支
  delegate = cases._default;

  // 从对象中对方法进行委派操作
  if ( cases.hasOwnProperty( key ) ) {
    delegate = cases[ key ];
  }

  // arg 的作用域可以设置成特定值,
  // 这种情况下,|null| 就可以了
  return delegate.apply( null, args );
};



delegator( "alpha", 1, 2, 3, 4, 5 );
// [ "Alpha", 5 ]

// 当然 `case` key 的值可以轻松地换成任意值

var caseKey, someUserInput;

// 有没有可能是某种形式的输入?
someUserInput = 9;

if ( someUserInput > 10 ) {
  caseKey = "alpha";
} else {
  caseKey = "beta";
}

// 或者...

caseKey = someUserInput > 10 ? "alpha" : "beta";

// 然后...

delegator( caseKey, someUserInput );
// [ "Beta", 1 ]

// 当然还可以这样搞...

delegator();
// [ "Default", 0 ]

Referrence:

idiomatic.js

Comments is loading...

Comments is loading...