ES6提出了兩個(gè)新的聲明變量的命令:let和const蛾魄。其中,let完全可以取代var逛拱,因?yàn)閮烧哒Z(yǔ)義相同敌厘,而且let沒(méi)有副作用
var命令存在變量提升效用,let命令沒(méi)有這個(gè)問(wèn)題
建議不再使用var命令朽合,而是使用let命令取代
1
2
3
4
5
"use strict";
if(true) {
console.log(x);// ReferenceError
letx ='hello';
}
上面代碼如果使用var替代let俱两,console.log那一行就不會(huì)報(bào)錯(cuò),而是會(huì)輸出undefined曹步,因?yàn)樽兞柯暶魈?/p>
升到代碼塊的頭部宪彩。這違反了變量先聲明后使用的原則
在let和const之間,建議優(yōu)先使用const箭窜,尤其是在全局環(huán)境毯焕,不應(yīng)該設(shè)置變量,只應(yīng)設(shè)置常量磺樱。這符合函數(shù)式編程思想纳猫,有利于將來(lái)的分布式運(yùn)算。
1
2
3
4
5
6
7
8
9
10
// bad
vara =1, b =2, c =3;
// good
consta =1;
constb =2;
constc =3;
// best
const[a, b, c] = [1,2,3];
const聲明常量還有兩個(gè)好處竹捉,一是閱讀代碼的人立刻會(huì)意識(shí)到不應(yīng)該修改這個(gè)值芜辕,二是防止了無(wú)意間修改
變量值所導(dǎo)致的錯(cuò)誤
所有的函數(shù)都應(yīng)該設(shè)置為常量
let表示的變量,只應(yīng)出現(xiàn)在單線程運(yùn)行的代碼中块差,不能是多線程共享的侵续,這樣有利于保證線程安全
V8引擎只在嚴(yán)格模式之下,支持let和const憨闰。結(jié)合前兩點(diǎn)状蜗,這實(shí)際上意味著,將來(lái)所有的編程都是針對(duì)嚴(yán)
格模式的鹉动。
靜態(tài)字符串一律使用單引號(hào),不使用雙引號(hào)泽示。動(dòng)態(tài)字符串使用反引號(hào)
1
2
3
4
5
6
7
8
9
// bad
consta ="foobar";
constb ='foo'+ a +'bar';
// good
consta ='foobar';
constb =`foo${a}bar`;
constc ='foobar';
使用數(shù)組成員對(duì)變量賦值蜜氨,優(yōu)先使用解構(gòu)賦值
1
2
3
4
5
6
7
8
constarr = [1,2,3,4];
// bad
constfirst = arr[0];
constsecond = arr[1];
// good
const[first, second] = arr;
函數(shù)的參數(shù)如果是對(duì)象的成員,優(yōu)先使用解構(gòu)賦值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// bad
functiongetFullName(user){
constfirstName = user.firstName;
constlastName = user.lastName;
}
// good
functiongetFullName(obj){
const{ firstName, lastName } = obj;
}
// best
functiongetFullName({ firstName, lastName }){
}
如果函數(shù)返回多個(gè)值捎泻,優(yōu)先使用對(duì)象的解構(gòu)賦值飒炎,而不是數(shù)組的解構(gòu)賦值。這樣便于以后添加返回值笆豁,以及更改返回值的順序
1
2
3
4
5
6
7
8
9
10
// bad
functionprocessInput(input){
return[left, right, top, bottom];
}
// good
functionprocessInput(input){
return{ left, right, top, bottom };
}
const{ left, right } = processInput(input);
單行定義的對(duì)象,最后一個(gè)成員不以逗號(hào)結(jié)尾渔呵。多行定義的對(duì)象怒竿,最后一個(gè)成員以逗號(hào)結(jié)尾
1
2
3
4
5
6
7
8
9
10
11
12
13
// bad
consta = {k1: v1,k2: v2, };
constb = {
k1: v1,
k2: v2
};
// good
consta = {k1: v1,k2: v2 };
constb = {
k1: v1,
k2: v2,
};
對(duì)象盡量靜態(tài)化,一旦定義扩氢,就不得隨意添加新的屬性耕驰。如果添加屬性不可避免,要使用Object.assign方法
1
2
3
4
5
6
7
8
9
10
11
// bad
consta = {};
a.x =3;
// if reshape unavoidable
consta = {};
Object.assign(a, {x:3});
// good
consta = {x:null};
a.x =3
如果對(duì)象的屬性名是動(dòng)態(tài)的录豺,可以在創(chuàng)造對(duì)象的時(shí)候朦肘,使用屬性表達(dá)式定義
1
2
3
4
5
6
7
8
9
10
11
12
13
// bad
constobj = {
id:5,
name:'San Francisco',
};
obj[getKey('enabled')] =true;'
// good
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enabled')]: true,
};
上面代碼中,對(duì)象obj的最后一個(gè)屬性名双饥,需要計(jì)算得到媒抠。這時(shí)最好采用屬性表達(dá)式,在新建obj的時(shí)候咏花,將該屬性與其他屬性定義在一起趴生。這樣一來(lái),所有屬性就在一個(gè)地方定義了
另外昏翰,對(duì)象的屬性和方法苍匆,盡量采用簡(jiǎn)潔表達(dá)法,這樣易于描述和書(shū)寫(xiě)棚菊。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ar ref ='some value';
// bad
constatom = {
ref: ref,
value:1,
addValue:function(value){
returnatom.value + value;
},
};
// good
constatom = {
ref,
value:1,
addValue(value) {
returnatom.value + value;
},
};
使用擴(kuò)展運(yùn)算符(...)拷貝數(shù)組
1
2
3
4
5
6
7
8
9
10
// bad
constlen = items.length;
constitemsCopy = [];
leti;
for(i =0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
constitemsCopy = [...items];
使用Array.from方法,將類(lèi)似數(shù)組的對(duì)象轉(zhuǎn)為數(shù)組
1
2
constfoo =document.querySelectorAll('.foo');
constnodes =Array.from(foo);
立即執(zhí)行函數(shù)可以寫(xiě)成箭頭函數(shù)的形式
1
2
3
(()=>{
console.log('Welcome to the Internet.');
})();
那些需要使用函數(shù)表達(dá)式的場(chǎng)合检碗,盡量用箭頭函數(shù)代替。因?yàn)檫@樣更簡(jiǎn)潔码邻,而且綁定了this
1
2
3
4
5
6
7
8
9
// bad
[1,2,3].map(function(x){
returnx * x;
});
// good
[1,2,3].map((x) =>{
returnx * x;
});
箭頭函數(shù)取代Function.prototype.bind折剃,不應(yīng)再用self/_this/that綁定this
1
2
3
4
5
6
7
8
9
10
11
// bad
constself =this;
constboundMethod =function(...params){
returnmethod.apply(self, params);
}
// acceptable
constboundMethod = method.bind(this);
// best
constboundMethod =(...params) =>method.apply(this, params);
所有配置項(xiàng)都應(yīng)該集中在一個(gè)對(duì)象,放在最后一個(gè)參數(shù)像屋,布爾值不可以直接作為參數(shù)
1
2
3
4
5
6
7
// bad
functiondivide(a, b, option = false){
}
// good
functiondivide(a, b, { option = false } = {}){
}
不要在函數(shù)體內(nèi)使用arguments變量微驶,使用rest運(yùn)算符(...)代替。因?yàn)閞est運(yùn)算符顯式表明你想要獲取參數(shù),而且arguments是一個(gè)類(lèi)似數(shù)組的對(duì)象因苹,而rest運(yùn)算符可以提供一個(gè)真正的數(shù)組
1
2
3
4
5
6
7
8
9
10
// bad
functionconcatenateAll(){
constargs =Array.prototype.slice.call(arguments);
returnargs.join('');
}
// good
functionconcatenateAll(...args){
returnargs.join('');
}
使用默認(rèn)值語(yǔ)法設(shè)置函數(shù)參數(shù)的默認(rèn)值
1
2
3
4
5
6
7
8
9
// bad
functionhandleThings(opts){
opts = opts || {};
}
// good
functionhandleThings(opts = {}){
// ...
}
注意區(qū)分Object和Map篇恒,只有模擬實(shí)體對(duì)象時(shí)扶檐,才使用Object。如果只是需要key:value的數(shù)據(jù)結(jié)構(gòu)胁艰,使用Map款筑。因?yàn)镸ap有內(nèi)建的遍歷機(jī)制
1
2
3
4
5
6
7
8
9
10
letmap =newMap(arr);
for(letkeyofmap.keys()) {
console.log(key);
}
for(letvalueofmap.values()) {
console.log(value);
}
for(letitemofmap.entries()) {
console.log(item[0], item[1]);
}
總是用class腾么,取代需要prototype操作奈梳。因?yàn)閏lass的寫(xiě)法更簡(jiǎn)潔,更易于理解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// bad
functionQueue(contents = []){
this._queue = [...contents];
}
Queue.prototype.pop =function(){
constvalue =this._queue[0];
this._queue.splice(0,1);
returnvalue;
}
// good
classQueue{
constructor(contents = []) {
this._queue = [...contents];
}
pop() {
constvalue =this._queue[0];
this._queue.splice(0,1);
returnvalue;
}
}
使用extends實(shí)現(xiàn)繼承解虱,因?yàn)檫@樣更簡(jiǎn)單攘须,不會(huì)有破壞instanceof運(yùn)算的危險(xiǎn)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// bad
constinherits =require('inherits');
functionPeekableQueue(contents){
Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek =function(){
returnthis._queue[0];
}
// good
classPeekableQueueextendsQueue{
peek() {
returnthis._queue[0];
}
}
Module語(yǔ)法是JavaScript模塊的標(biāo)準(zhǔn)寫(xiě)法殴泰,堅(jiān)持使用這種寫(xiě)法于宙。使用import取代require
1
2
3
4
5
6
7
// bad
constmoduleA =require('moduleA');
constfunc1 = moduleA.func1;
constfunc2 = moduleA.func2;
// good
import{ func1, func2 }from'moduleA';
使用export取代module.exports
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// commonJS的寫(xiě)法
varReact =require('react');
varBreadcrumbs = React.createClass({
render() {
return;
}
});
module.exports = Breadcrumbs;
// ES6的寫(xiě)法
import React from 'react';
const Breadcrumbs = React.createClass({
render() {
return;
}
});
export default Breadcrumbs
不要在模塊輸入中使用通配符。因?yàn)檫@樣可以確保你的模塊之中悍汛,有一個(gè)默認(rèn)輸出(export default)
1
2
3
4
5
// bad
import*asmyObject'./importModule';
// good
importmyObjectfrom'./importModule';
如果模塊默認(rèn)輸出一個(gè)函數(shù)捞魁,函數(shù)名的首字母應(yīng)該小寫(xiě)
1
2
3
functionmakeStyleGuide(){
}
exportdefaultmakeStyleGuide;
如果模塊默認(rèn)輸出一個(gè)對(duì)象,對(duì)象名的首字母應(yīng)該大寫(xiě)
1
2
3
4
5
constStyleGuide = {
es6: {
}
};
exportdefaultStyleGuide;