国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

Airbnb JavaScript Style 閱讀注解

msup / 3573人閱讀

摘要:閱讀注解提供一種合理的的規(guī)范,對(duì)原文主要內(nèi)容進(jìn)行翻譯,同時(shí)對(duì)部分內(nèi)容進(jìn)行注釋。聲明時(shí)需要指定其值作為一個(gè)常數(shù)的初始化器。這樣可以避免為這些屬性創(chuàng)建臨時(shí)引用,保持代碼的整潔使用數(shù)組解構(gòu)使用對(duì)象解構(gòu)而不是數(shù)組解構(gòu)來(lái)實(shí)現(xiàn)多個(gè)返回值。

Airbnb JavaScript Style 閱讀注解

提供一種合理的javascript的規(guī)范,對(duì)原文主要內(nèi)容進(jìn)行翻譯,同時(shí)對(duì)部分內(nèi)容進(jìn)行注釋。推薦大家先收藏,在寫(xiě)代碼的時(shí)候可以方便參考。

注意:本文假定你正在使用 Babel,并且要求你使用 babel-preset-airbnb或者其替代品。同時(shí),假定你已經(jīng)通過(guò)airbnb-browser-shims或者其替代品安裝 shims/polyfills 在你的app內(nèi)。

如果您想閱讀原文?

Airbnb JavaScript Style Guide Origin

如果您想在github上查看?

Airbnb JavaScript Style Guide In Chinese

如果您想了解并使用 babel with airbnb?

Babel with Airbnb

Types(數(shù)據(jù)類(lèi)型)

簡(jiǎn)單的基本數(shù)據(jù)類(lèi)型,直接使用其值

- `string`

- `number`

- `boolean`

- `null`

- `undefined`

- `symbol`

const foo = 1;
let bar = foo;
bar = 9;
console.log(foo, bar); // => 1, 9

復(fù)雜的基本數(shù)據(jù)類(lèi)型,直接使用其值的引用

- `object`

- `array`

- `function`

const foo = [1, 2];
const bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9
?symbol

Symbol

symbol自ES6引入,目的是提供一種機(jī)制,保證每個(gè)屬性名都是唯一的,從根本上防止屬性名的沖突。在這之前,對(duì)象屬性名都是字符串。其實(shí)看到這里,stringsymbol類(lèi)型有點(diǎn)classid的意思

Symbol()的聲明,因?yàn)?Symbol()返回值是一個(gè)類(lèi)似于字符串的基本類(lèi)型,不是一個(gè)對(duì)象,所以不能使用 new 命令

let ylone = Symbol();
typeof(ylone);
?    
"symbol"
  
//為聲明加上描述
let ylone1 = Symbol("hello");
ylone1;
?
Symbol(hello);

無(wú)論是不加描述,還是所加的描述相同, Symbol() 函數(shù)的返回值都不相同

Symbol.for("key") 也會(huì)返回一個(gè)Symbol,但是Symbol.for()采用登記機(jī)制(會(huì)被登記在全局環(huán)境中供搜索),如果之前key已經(jīng)存在,則直接返回該值,否則新建一個(gè)值。比如,如果你調(diào)用 Symbol.for("cat")30 次,每次都會(huì)返回同一個(gè)Symbol值,但是調(diào)用Symbol("cat")30 次,會(huì)返回 30 個(gè)不同的Symbol值。

Symbol本身不能與其他值進(jìn)行運(yùn)算,但是可以轉(zhuǎn)換成字符串和布爾類(lèi)型

對(duì)象中使用Symbol()。通過(guò)對(duì)比之前通過(guò) a["string"] 的方式,相當(dāng)于多了一步轉(zhuǎn)換,來(lái)保證屬性命名的安全。

let mySymbol = Symbol();
// 第一種寫(xiě)法
let a = {};
a[mySymbol] = "Hello!";
  
// 第二種寫(xiě)法
let a = {
    [mySymbol]: "Hello!"
};
    
// 第三種寫(xiě)法
let a = {};
Object.defineProperty(a, mySymbol, { value: "Hello!" });
    
a[mySymbol]
?
"hello!"    

注意,由于 . 運(yùn)算符后面總是字符串,所以Symbol() 不支持點(diǎn)式聲明對(duì)象屬性。在對(duì)象內(nèi)部使用 [symbol] 這樣的寫(xiě)法也是這個(gè)道理

References(引用)

聲明創(chuàng)建一個(gè)值時(shí)用 const 而不用 var,這樣可以保證你聲明的值不會(huì)被重定義

// bad
var a = 1;
var b = 2;

// good
const a = 1;
const b = 2;

如果需要改變聲明所創(chuàng)建的值,用let而不是var,因?yàn)?let 是塊級(jí)作用域元素, var 是函數(shù)作用域元素

// bad
var count = 1;
if (true) {
  count += 1;
}

// good, use the let.
let count = 1;
if (true) {
  count += 1;
}

注意,letconst 都是塊級(jí)作用域函數(shù),他們都只存在于他們被定義的塊中

// const and let only exist in the blocks they are defined in.
{
  let a = 1;
  const b = 1;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError
?const,let,block-scoped,function-scoped

const

塊級(jí)作用域的常量,此聲明創(chuàng)建一個(gè)常量,其作用域可以是全局或本地聲明的。聲明時(shí)需要指定其值作為一個(gè)常數(shù)的初始化器。一般情況下, const 聲明的值不能改變,但是對(duì)象元素可以改變其屬性,數(shù)組元素可以向其中添加值,但是不能重新賦值

const a = 100;
a = 10; ? Uncaught TypeError: Assignment to constant variable
    
const a = [];
a.push("a"); ?
a = ["a"]; ? Uncaught TypeError: Assignment to constant variable
    
const obj = {"name":"ylone"};
obj["name"] = "yh";    ?
obj = {"name":"yh"}; ? Uncaught TypeError: Assignment to constant variable

注意,chrome30嚴(yán)格模式下不能使用,const(Uncaught SyntaxError: Use of const in strict mode. )

let

let允許你聲明一個(gè)作用域被限制在塊級(jí)中的變量、語(yǔ)句或者表達(dá)式。let聲明的變量只在其聲明的塊或子塊中可用,這一點(diǎn),與var相似。二者之間最主要的區(qū)別在于var聲明的變量的作用域是整個(gè)封閉函數(shù)。

var q = 1;
var w = 2;
if(true){
var q = 11;
let w = 22;
console.log(q,w); ?(11,22)
}
console.log(q,w); ?(11,2)

block-scoped

在其他類(lèi)C語(yǔ)言中,由 {} 封閉的代碼塊即為 block-scoped,{..block-scoped..}

if(true){
var a = 100;
}
a; ? 100
    
if(true){
let b = 100;
}
b; ? Uncaught ReferenceError: b is not defined

如果是類(lèi)C語(yǔ)言中,a 會(huì)在if語(yǔ)句執(zhí)行完畢后銷(xiāo)毀,但是在javascript中,if中的變量聲明會(huì)將變臉那個(gè)添加到當(dāng)前的執(zhí)行環(huán)境中,這里可以看出 var與let的區(qū)別var 聲明的變量會(huì)自動(dòng)被添加到最接近的執(zhí)行環(huán)境中,let聲明的變量則只會(huì)存在與塊級(jí)作用域中

function-scoped

函數(shù)作用域,每個(gè)函數(shù)被聲明時(shí)的上下文執(zhí)行環(huán)境,fucnction(){..function-scoped..}

Objects(對(duì)象)

直接使用 {} 來(lái)創(chuàng)建對(duì)象,因?yàn)檫@樣更加簡(jiǎn)潔,性能上和 new Object() 也沒(méi)差

// bad
const item = new Object();

// good
const item = {};

創(chuàng)建擁有動(dòng)態(tài)屬性名的對(duì)象時(shí),用計(jì)算機(jī)屬性名來(lái)表示,這樣可以在創(chuàng)建對(duì)象時(shí),將所有的屬性寫(xiě)在同一個(gè)地方

function getKey(k) {
  return `a key named ${k}`;
}

// bad
const obj = {
  id: 5,
  name: "San Francisco",
};
obj[getKey("enabled")] = true;

// good
const obj = {
  id: 5,
  name: "San Francisco",
  [getKey("enabled")]: true,
};

對(duì)象屬性中有函數(shù)方法時(shí),使用更簡(jiǎn)潔的對(duì)象字面值方法

// bad
const atom = {
  value: 1,
  addValue: function (value) {
    return atom.value + value;
  },
};

// good
const atom = {
  value: 1,
  addValue(value) {
    return atom.value + value;
  },
};

對(duì)象屬性和屬性值一致時(shí),使用更簡(jiǎn)潔的對(duì)象字面值屬性

const lukeSkywalker = "Luke Skywalker";

// bad
const obj = {
  lukeSkywalker: lukeSkywalker,
};

// good
const obj = {
  lukeSkywalker,
};

聲明對(duì)象時(shí),根據(jù)是否使用速記,簡(jiǎn)單地對(duì)對(duì)象的屬性分下類(lèi)

const anakinSkywalker = "Anakin Skywalker";
const lukeSkywalker = "Luke Skywalker";

// bad
const obj = {
  episodeOne: 1,
  twoJediWalkIntoACantina: 2,
  lukeSkywalker,
  episodeThree: 3,
  mayTheFourth: 4,
  anakinSkywalker,
};

// good
const obj = {
  lukeSkywalker,
  anakinSkywalker,
  episodeOne: 1,
  twoJediWalkIntoACantina: 2,
  episodeThree: 3,
  mayTheFourth: 4,
};

僅給有特殊符號(hào)的標(biāo)識(shí)符提供引號(hào),實(shí)際上對(duì)象的屬性默認(rèn)為字符串類(lèi)型,除非用[]標(biāo)記為符號(hào)類(lèi)型。這樣做的好處在于,增強(qiáng)代碼高亮,方便閱讀,并且對(duì)js引擎更加友好

// bad
const bad = {
  "foo": 3,
  "bar": 4,
  "data-blah": 5,
};

// good
const good = {
  foo: 3,
  bar: 4,
  "data-blah": 5,
};

不要直接調(diào)用Object.prototype下的方法,比如 hasOwnProperty,isPrototypeOf,propertyIsEnumerable等,因?yàn)檫@些方法可能被覆蓋{ hasOwnProperty: false } ,或者對(duì)象為空?qǐng)?bào)錯(cuò)

// bad
console.log(object.hasOwnProperty(key));

// good
console.log(Object.prototype.hasOwnProperty.call(object, key));

// best
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
/* or */
import has from "has"; // https://www.npmjs.com/package/has
// ...
console.log(has.call(object, key));

用對(duì)象擴(kuò)散運(yùn)算符和對(duì)象剩余運(yùn)算符,而不是 Object.assign 來(lái)進(jìn)行淺拷貝操作

// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // this mutates `original` ?_?
delete copy.a; // so does this

// bad
const original = { a: 1, b: 2 };
const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }

// good
const original = { a: 1, b: 2 };
const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }

 // noA => { b: 2, c: 3 }
?call,assign(),...

call()

Function.prototype.call(),調(diào)用一個(gè)函數(shù),其具有指定的 this 值和參數(shù)列表。注意,該方法和 apply() 方法類(lèi)似,區(qū)別在于 apply() 傳參為一個(gè)包含多個(gè)參數(shù)的數(shù)組。可以讓call()中的對(duì)象調(diào)用當(dāng)前對(duì)象所擁有的function。

使用 call() 調(diào)用父構(gòu)造函數(shù),在一個(gè)子構(gòu)造函數(shù)中,你可以通過(guò)調(diào)用父構(gòu)造函數(shù)的 call 方法來(lái)實(shí)現(xiàn)繼承,類(lèi)似于Java中的寫(xiě)法

//父構(gòu)造函數(shù),寫(xiě)一些公用的方法和屬性
function a(v1,v2){
    this.name = v1;
    this.cool = v2;
} 
//子構(gòu)造函數(shù),可以繼承父構(gòu)造函數(shù)的方法和屬性,同時(shí)可以有私有的方法和屬性
function b(v1,v2,v3){
    a.call(this,v1,v2);
    this.sex = v3;
}
var v1 = new a("ylone",true);
var v2 = new b("ylone",true,"male");
v1; ? {name: "ylone", cool: true}
v2; ? {name: "ylone", cool: true, sex: "male"}

使用 call() 調(diào)用匿名函數(shù),將參數(shù)作為指定的 this值,傳進(jìn)匿名函數(shù)。同時(shí)也可以傳遞普通參數(shù)。

var i = 1;
(function(i){console.log(this,i)}).call(Math.random(),i);
? 0.9604319664333041 1

使用 call() 調(diào)用函數(shù)并且指定執(zhí)行環(huán)境的this

function a(){
    console.log(this.name + " is " + this.cool);
};
var i = {name: "ylone", cool: "cool"};
a.call(i); ? ylone is cool

Object.assign()

$.extend()類(lèi)似,用于對(duì)象的合并,將源對(duì)象內(nèi)所有可枚舉的屬性拷貝到目標(biāo)對(duì)象,注意如果源數(shù)據(jù)不是對(duì)象,則先會(huì)轉(zhuǎn)換成對(duì)象;如果是null或者undefined等不能轉(zhuǎn)換成對(duì)象的類(lèi)型,則根據(jù)其位置進(jìn)行跳過(guò)或者報(bào)錯(cuò)。

Object.assign(null); ? Uncaught TypeError: Cannot convert undefined or null to object
  
Object.assign(1,null); ? Number?{1}

Object.assign()僅支持淺拷貝,也就是說(shuō),如果源對(duì)象某個(gè)屬性的值是對(duì)象,那么目標(biāo)對(duì)象拷貝得到的是這個(gè)對(duì)象的引用

var v1 = {a:{b:"b"}};
var v2 = Object.assign({},v1);
v1.a.b = "c";
v2.a.b; ? "c"

Object.assign() 處理數(shù)組,會(huì)先把數(shù)組轉(zhuǎn)換成對(duì)象,將其視為屬性名為 0、1、2 的對(duì)象,因此源數(shù)組的 0 號(hào)屬性4覆蓋了目標(biāo)數(shù)組的 0 號(hào)屬性1。

Object.assign([1, 2, 3], [4, 5]);
?
Object.assign({0:1,1:2,2:3},{0:4,1:5});
?
{0:4,1:5,2:3}
?
[4,5,3]

...

對(duì)象擴(kuò)散運(yùn)算符和對(duì)象剩余運(yùn)算符都用 ... 表示,可以理解為“脫衣服”方法

數(shù)組轉(zhuǎn)換,將數(shù)組轉(zhuǎn)換成逗號(hào)分隔的參數(shù)序列,注意,其返回值并不是某個(gè)基本類(lèi)型,所以該方法多用于函數(shù)參數(shù)設(shè)置,代替 apply() 方法。對(duì)于很多參數(shù)不能接受數(shù)組的方法提供了便利。

...[1,2,3] ? Uncaught SyntaxError: Unexpected number
  
[...[1,2,3]] ? [1, 2, 3]
  
[1,...[2,3],4] ? [1, 2, 3, 4]
  
//Math.max()不支持?jǐn)?shù)組傳參,之前通過(guò)apply()進(jìn)行轉(zhuǎn)換
Math.max.apply(null,[1,2,3]) ? 3
//現(xiàn)在可以利用 ... 直接進(jìn)行轉(zhuǎn)換
Math.max(...[1,2,3]) ? 3
Arrays(數(shù)組)

使用 [] 來(lái)創(chuàng)建數(shù)組

// bad
const items = new Array();

// good
const items = [];

使用 push() 而不是直接給數(shù)組項(xiàng)賦值

const someStack = [];

// bad
someStack[someStack.length] = "abracadabra";

// good
someStack.push("abracadabra");

使用 ... 拷貝數(shù)組

// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i += 1) {
  itemsCopy[i] = items[i];
}

// good
const itemsCopy = [...items];

使用 ... 將數(shù)組對(duì)象轉(zhuǎn)換為數(shù)組

const foo = document.querySelectorAll(".foo");

// good
const nodes = Array.from(foo);

// best
const nodes = [...foo];

array.from() 而不是 ... 遍歷迭代器,這樣避免產(chǎn)生了中間變量

// bad
const baz = [...foo].map(bar);

// good
const baz = Array.from(foo, bar);

數(shù)組方法的回調(diào)中使用return語(yǔ)句,如果函數(shù)體由單語(yǔ)句組成,返回值沒(méi)有副作用,return也可以忽略

// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});

// good
[1, 2, 3].map(x => x + 1);

// bad - no returned value means `memo` becomes undefined after the first iteration
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
  const flatten = memo.concat(item);
  memo[index] = flatten;
});

// good
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
  const flatten = memo.concat(item);
  memo[index] = flatten;
  return flatten;
});

// bad
inbox.filter((msg) => {
  const { subject, author } = msg;
  if (subject === "Mockingbird") {
    return author === "Harper Lee";
  } else {
    return false;
  }
});

// good
inbox.filter((msg) => {
  const { subject, author } = msg;
  if (subject === "Mockingbird") {
    return author === "Harper Lee";
  }

  return false;
});

如果數(shù)組有多行,在數(shù)組項(xiàng)開(kāi)始和結(jié)束時(shí)使用換行符

// bad
const arr = [
  [0, 1], [2, 3], [4, 5],
];

const objectInArray = [{
  id: 1,
}, {
  id: 2,
}];

const numberInArray = [
  1, 2,
];

// good
const arr = [[0, 1], [2, 3], [4, 5]];

const objectInArray = [
  {
    id: 1,
  },
  {
    id: 2,
  },
];

const numberInArray = [
  1,
  2,
];
?Array.from()

Array.from()

Array.from() 方法從一個(gè)類(lèi)似數(shù)組(一個(gè)對(duì)象必須有l(wèi)ength屬性)或可迭代對(duì)象中創(chuàng)建一個(gè)新的數(shù)組實(shí)例,比如 array,map,set,string

 //數(shù)組
 const arr = ["1","2","3"];
 Array.from(arr); ? ["1", "2", "3"]

 //字符串
 const str = "ylone";
 Array.from(str); ? ["y", "l", "o", "n", "e"]

 //map對(duì)象
 const m1 = new Map();
 m1.set("v1",1);
 m2.set("v2",2);
 m2; ? {"v1" => 1, "v2" => 2} 
 Array.from(m2); ? [["v1",1],["v2",2]]

 //json對(duì)象
 const j = {"v1":1,"v2":2};
 j.length; ? undefined
 Array.from(j); ? []  

Array.from(arrayLike, mapFn, thisArg)

arrayLike表示想要轉(zhuǎn)換成數(shù)組的偽數(shù)組對(duì)象或可迭代對(duì)象

mapFn(可選參數(shù))表示新數(shù)組中的每個(gè)元素會(huì)執(zhí)行該回調(diào)函數(shù)

thisArg(可選參數(shù))表示執(zhí)行回調(diào)函數(shù)mapFn時(shí)this對(duì)象

   Array.from([1,2,3], function(n){return n+1})
   ?
   [2, 3, 4]
Destructuring(解構(gòu))

訪(fǎng)問(wèn)和使用對(duì)象的多個(gè)屬性時(shí),使用對(duì)象解構(gòu)。這樣可以避免為這些屬性創(chuàng)建臨時(shí)引用,保持代碼的整潔

// bad
function getFullName(user) {
  const firstName = user.firstName;
  const lastName = user.lastName;

  return `${firstName} ${lastName}`;
}

// good
function getFullName(user) {
  const { firstName, lastName } = user;
  return `${firstName} ${lastName}`;
}

// best
function getFullName({ firstName, lastName }) {
  return `${firstName} ${lastName}`;
}

使用數(shù)組解構(gòu)

const arr = [1, 2, 3, 4];

// bad
const first = arr[0];
const second = arr[1];

// good
const [first, second] = arr;

使用對(duì)象解構(gòu)而不是數(shù)組解構(gòu)來(lái)實(shí)現(xiàn)多個(gè)返回值。這樣,您可以添加新的屬性或者更改屬性順序

// bad
function processInput(input) {
  return [left, right, top, bottom];
}

// the caller needs to think about the order of return data
const [left, __, top] = processInput(input);

// good
function processInput(input) {
  return { left, right, top, bottom };
}

// the caller selects only the data they need
const { left, top } = processInput(input);
?Destructuring

Destructuring:解構(gòu)。解構(gòu)的作用是可以快速取得數(shù)組或?qū)ο螽?dāng)中的元素或?qū)傩裕鵁o(wú)需使用arr[x]或者obj[key]等傳統(tǒng)方式進(jìn)行賦值

  //數(shù)組解構(gòu)
  const arr = [1,[2,3],4];
  const [a,[b,c],d] = arr;
  a,b,c,d; ? 1,2,3,4
  //函數(shù)傳參
  var arr = [1, 2, 3];
  function fn1([a, b, c]) {
    return a+b+c;
  }
  fn1(arr); ? 6
Strings(字符串)

使用單引號(hào) ""

// bad
const name = "Capt. Janeway";

// bad - template literals should contain interpolation or newlines
const name = `Capt. Janeway`;

// good
const name = "Capt. Janeway";

如果字符串很長(zhǎng),不要通過(guò)字符串連接符進(jìn)行換行,保持原來(lái)的字符串形式就好。因?yàn)槠茐淖址且患懿缓玫氖虑椋瑫r(shí)也減少了代碼的可讀性

// bad
const errorMessage = "This is a super long error that was thrown because 
of Batman. When you stop to think about how Batman had anything to do 
with this, you would get nowhere 
fast.";

// bad
const errorMessage = "This is a super long error that was thrown because " +
  "of Batman. When you stop to think about how Batman had anything to do " +
  "with this, you would get nowhere fast.";

// good
const errorMessage = "This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.";

當(dāng)字符串中有變量時(shí),使用模板字符串而不是連字符。這樣代碼更加簡(jiǎn)潔可讀

// bad
function sayHi(name) {
  return "How are you, " + name + "?";
}

// bad
function sayHi(name) {
  return ["How are you, ", name, "?"].join();
}

// bad
function sayHi(name) {
  return `How are you, ${ name }?`;
}

// good
function sayHi(name) {
  return `How are you, ${name}?`;
}

不要使用eval()方法,因?yàn)樗袧撛诘奈kU(xiǎn),在不受信任的代碼上使用可以打開(kāi)一個(gè)程序多達(dá)幾種不同的注入攻擊

在字符串中不要隨意使用 ,因?yàn)樗绊懣勺x性,同時(shí)可能與轉(zhuǎn)義符產(chǎn)生影響

// bad
const foo = ""this" is "quoted"";

// good
const foo = ""this" is "quoted"";
const foo = `my name is "${name}"`;
Functions(函數(shù))

使用命名函數(shù)表達(dá)式而不是函數(shù)聲明。因?yàn)槿绻粋€(gè)函數(shù)聲明被掛起之后,很容易在它被定義之前就去引用,這就很影響代碼的可讀性和可維護(hù)性。同時(shí),如果一個(gè)函數(shù)的功能比較復(fù)雜,需要用函數(shù)名來(lái)對(duì)其進(jìn)行一定的描述

// bad
function foo() {
  // ...
}

// bad
const foo = function () {
  // ...
};

// good
// lexical name distinguished from the variable-referenced invocation(s)
const short = function longUniqueMoreDescriptiveLexicalFoo() {
  // ...
};

() 創(chuàng)建的函數(shù)需要立即調(diào)用,自調(diào)用函數(shù)相當(dāng)于一個(gè)獨(dú)立模塊。事實(shí)上,IIFE很少在項(xiàng)目中使用

// immediately-invoked function expression (IIFE)
(function () {
  console.log("Welcome to the Internet. Please follow me.");
}());

不要在非功能模塊(if,while等)里面聲明一個(gè)函數(shù)。將函數(shù)分配給一個(gè)變量來(lái)替代它。因?yàn)殡m然瀏覽器支持這種做法,但是他們各自的解析方式并不一樣

ECMA-262 定義 ‘塊’ 表示一個(gè)語(yǔ)句列表,函數(shù)聲明并不是一個(gè)語(yǔ)句,跟上一點(diǎn)類(lèi)似

// bad
if (currentUser) {
  function test() {
    console.log("Nope.");
  }
}

// good
let test;
if (currentUser) {
  test = () => {
    console.log("Yup.");
  };
}

永遠(yuǎn)不要給參數(shù)命名為 arguments,這將導(dǎo)致每個(gè)函數(shù)作用域的 arguments對(duì)象被優(yōu)先替換

// bad
function foo(name, options, arguments) {
  // ...
}

// good
function foo(name, options, args) {
  // ...
}

永遠(yuǎn)不要使用 arguments,而使用 ...,因?yàn)?arguments 只是類(lèi)似數(shù)組

// bad
function concatenateAll() {
  const args = Array.prototype.slice.call(arguments);
  return args.join("");
}

// good
function concatenateAll(...args) {
  return args.join("");
}

使用函數(shù)默認(rèn)參數(shù)語(yǔ)法而不是改變函數(shù)的參數(shù)

// really bad
function handleThings(opts) {
  // No! We shouldn’t mutate function arguments.
  // Double bad: if opts is falsy it"ll be set to an object which may
  // be what you want but it can introduce subtle bugs.
  opts = opts || {};
  // ...
}

// still bad
function handleThings(opts) {
  if (opts === void 0) {
    opts = {};
  }
  // ...
}

// good
function handleThings(opts = {}) {
  // ...
}

避免函數(shù)默認(rèn)參數(shù)使用不當(dāng),使用時(shí)要考慮場(chǎng)景

var b = 1;
// bad
function count(a = b++) {
  console.log(a);
}
count();  // 1
count();  // 2
count(3); // 3
count();  // 3

總是將函數(shù)默認(rèn)參數(shù)放在傳參的最后

// bad
function handleThings(opts = {}, name) {
  // ...
}

// good
function handleThings(name, opts = {}) {
  // ...
}

永遠(yuǎn)不要使用 Function 構(gòu)造函數(shù)來(lái)創(chuàng)建一個(gè)新的函數(shù),因?yàn)樗?eval() 沆瀣一氣

// bad
var add = new Function("a", "b", "return a + b");

// still bad
var subtract = Function("a", "b", "return a - b");

函數(shù)簽名的間距,添加或刪除名稱(chēng)時(shí)不需要添加或刪除空格,保持一致性

// bad
const f = function(){};
const g = function (){};
const h = function() {};

// good
const x = function () {};
const y = function a() {};

不要改變參數(shù),因?yàn)椴僮髯顬閰?shù)傳入的對(duì)象可能會(huì)改變?cè)瓕?duì)象從而對(duì)其他調(diào)用產(chǎn)生影響

// bad
function f1(obj) {
  obj.key = 1;
}

// good
function f2(obj) {
  const key = Object.prototype.hasOwnProperty.call(obj, "key") ? obj.key : 1;
}

不要重新分配參數(shù),特別是在訪(fǎng)問(wèn)arguments對(duì)象時(shí)

// bad
function f1(a) {
  a = 1;
  // ...
}

function f2(a) {
  if (!a) { a = 1; }
  // ...
}
 
// good
function f3(a) {
  const b = a || 1;
  // ...
}

function f4(a = 1) {
  // ...
}

優(yōu)先使用 ... 來(lái)調(diào)用可變參數(shù)函數(shù),因?yàn)?... 很干凈,不需要提供上下文環(huán)境,并且你不能輕易地使用 apply()new方法

// bad
const x = [1, 2, 3, 4, 5];
console.log.apply(console, x);

// good
const x = [1, 2, 3, 4, 5];
console.log(...x);

// bad
new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));

// good
new Date(...[2016, 8, 5]);

使用函數(shù)如果有多行簽名或者調(diào)用,應(yīng)該每個(gè) item 多帶帶放一行,并在最后一項(xiàng)放置一個(gè)尾隨逗號(hào)

// bad
function foo(bar,
             baz,
             quux) {
  // ...
}

// good
function foo(
  bar,
  baz,
  quux,
) {
  // ...
}
// bad
console.log(foo,
  bar,
  baz);
   
// good
console.log(
  foo,
  bar,
  baz,
);
?Default Function Parameter

函數(shù)默認(rèn)參數(shù),允許在沒(méi)有值或undefined被傳入時(shí)使用默認(rèn)形參

函數(shù)形式:function(name){param1 = defaultValue1,...,paramN = defaultValueN}

JavaScript中函數(shù)的參數(shù)默認(rèn)是 undefined

const a = function test(v1,v2=1){
    return v1*v2;
}
a(5,5); ? 25
a(5); ? 5
a(void 0,5); ? NaN  

可以看出,當(dāng)設(shè)置了函數(shù)默認(rèn)參數(shù)后,如果傳參為 undefined,則會(huì)用默認(rèn)參數(shù)替換,否則為原傳參值

有默認(rèn)值的解構(gòu)函數(shù),通過(guò)解構(gòu)賦值為參數(shù)賦值

const b = function test([a,b]=[1,2],{c:c}={c:3}){
  return a+b+c;
}
b(); ? 6
b([2,3],4); ? 9
b(void 0,4); ? 9
b([void 0,3],4); ? NaN

Arrow Functions(箭頭函數(shù))

當(dāng)需要使用一個(gè)匿名函數(shù)時(shí)(比如在傳遞內(nèi)聯(lián)回調(diào)時(shí)),使用箭頭函數(shù)表示

// bad
[1, 2, 3].map(function (x) {
  const y = x + 1;
  return x * y;
});

// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});

如果一個(gè)函數(shù)的返回值是一個(gè)無(wú)副作用的單語(yǔ)句,則省略大括號(hào)并且隱式返回,否則保留大括號(hào)并且使用return聲明

// bad
[1, 2, 3].map(number => {
  const nextNumber = number + 1;
  `A string containing the ${nextNumber}.`;
});

// good
[1, 2, 3].map(number => `A string containing the ${number}.`);

// good
[1, 2, 3].map((number) => {
  const nextNumber = number + 1;
  return `A string containing the ${nextNumber}.`;
});

// good
[1, 2, 3].map((number, index) => ({
  [index]: number,
}));

// No implicit return with side effects
function foo(callback) {
  const val = callback();
  if (val === true) {
    // Do something if callback returns true
  }
}

let bool = false;

// bad
foo(() => bool = true);

// good
foo(() => {
  bool = true;
});

如果函數(shù)表達(dá)式有多行,用括號(hào)將內(nèi)容包裹起來(lái),以便更好地閱讀,因?yàn)樗宄龢?biāo)記了起始和結(jié)束位置

// bad
["get", "post", "put"].map(httpMethod => Object.prototype.hasOwnProperty.call(
    httpMagicObjectWithAVeryLongName,
    httpMethod,
  )
);

// good
["get", "post", "put"].map(httpMethod => (
  Object.prototype.hasOwnProperty.call(
    httpMagicObjectWithAVeryLongName,
    httpMethod,
  )
));

如果函數(shù)內(nèi)始終只有一個(gè)參數(shù),則省略括號(hào),否則的話(huà),用括號(hào)保護(hù)參數(shù)

// bad
[1, 2, 3].map((x) => x * x);

// good
[1, 2, 3].map(x => x * x);

// good
[1, 2, 3].map(number => (
  `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`
));

// bad
[1, 2, 3].map(x => {
  const y = x + 1;
  return x * y;
});

// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});

避免將箭頭函數(shù)語(yǔ)法(=>)與比較運(yùn)算符(<=,>=)混淆

// bad
const itemHeight = item => item.height > 256 ? item.largeSize : item.smallSize;

// bad
const itemHeight = (item) => item.height > 256 ? item.largeSize : item.smallSize;

// good
const itemHeight = item => (item.height > 256 ? item.largeSize : item.smallSize);

// good
const itemHeight = (item) => {
  const { height, largeSize, smallSize } = item;
  return height > 256 ? largeSize : smallSize;
};
?arrow Function

箭頭函數(shù)表達(dá)式的語(yǔ)法比函數(shù)表達(dá)式更短,并且不綁定自己的this,arguments,super或 new.target。這些函數(shù)表達(dá)式最適合用于非方法函數(shù),并且它們不能用作構(gòu)造函數(shù)

const 函數(shù)名 = (參數(shù)...) => {函數(shù)聲明}||表達(dá)式

執(zhí)行體為函數(shù)聲明時(shí)需要加上 {},參數(shù)的規(guī)則參看上文內(nèi)容

//支持解構(gòu)函數(shù)
const f = ([a,b]=[1,2],{c:c}={c:3})=>a+b+c;
f(); ? 6;

Classes & Constructors(類(lèi)與構(gòu)造函數(shù))

避免直接使用 prototype , 多用 class。因?yàn)?class語(yǔ)法更加簡(jiǎn)潔和且閱讀性更棒

// bad
function Queue(contents = []) {
  this.queue = [...contents];
}
Queue.prototype.pop = function () {
  const value = this.queue[0];
  this.queue.splice(0, 1);
  return value;
};

// good
class Queue {
  constructor(contents = []) {
    this.queue = [...contents];
  }
  pop() {
    const value = this.queue[0];
    this.queue.splice(0, 1);
    return value;
  }
}

使用 extends 實(shí)現(xiàn)繼承,因?yàn)檫@是繼承原型的內(nèi)置功能

// bad
const inherits = require("inherits");
function PeekableQueue(contents) {
  Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function () {
  return this.queue[0];
};

// good
class PeekableQueue extends Queue {
  peek() {
    return this.queue[0];
  }
}

方法可以通過(guò)返回 this 來(lái)優(yōu)化方法鏈

// bad
Jedi.prototype.jump = function () {
  this.jumping = true;
  return true;
};

Jedi.prototype.setHeight = function (height) {
  this.height = height;
};

const luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined

// good
class Jedi {
  jump() {
    this.jumping = true;
    return this;
  }

  setHeight(height) {
    this.height = height;
    return this;
  }
}

const luke = new Jedi();

luke.jump()
luke.setHeight(20);

寫(xiě)一個(gè)通用的 toString() 方法也沒(méi)問(wèn)題,但是需要保證其能執(zhí)行且沒(méi)有其他影響

class Jedi {
  constructor(options = {}) {
    this.name = options.name || "no name";
  }

  getName() {
    return this.name;
  }

  toString() {
    return `Jedi - ${this.getName()}`;
  }
}

如果沒(méi)有指定類(lèi),那么類(lèi)需要有一個(gè)默認(rèn)的構(gòu)造方法。一個(gè)空的構(gòu)造函數(shù)或者只是委托給父類(lèi)是沒(méi)有必要的

// bad
class Jedi {
  constructor() {}

  getName() {
    return this.name;
  }
}

// bad
class Rey extends Jedi {
  constructor(...args) {
    super(...args);
  }
}

// good
class Rey extends Jedi {
  constructor(...args) {
    super(...args);
    this.name = "Rey";
  }
}

避免出現(xiàn)兩個(gè)一樣的類(lèi)成員,因?yàn)榍耙粋€(gè)成員會(huì)被覆蓋從而導(dǎo)致錯(cuò)誤

// bad
class Foo {
  bar() { return 1; }
  bar() { return 2; }
}

// good
class Foo {
  bar() { return 1; }
}

// good
class Foo {
  bar() { return 2; }
}
Modules(模塊)

始終使用模塊(import/export)來(lái)代替非標(biāo)準(zhǔn)的模塊系統(tǒng)。你可以選擇你喜歡的模塊系統(tǒng),因?yàn)槟K代表未來(lái)

// bad
const AirbnbStyleGuide = require("./AirbnbStyleGuide");
module.exports = AirbnbStyleGuide.es6;

// ok
import AirbnbStyleGuide from "./AirbnbStyleGuide";
export default AirbnbStyleGuide.es6;

// best
import { es6 } from "./AirbnbStyleGuide";
export default es6;

不要使用通配符進(jìn)行導(dǎo)出,從而保證你輸出一個(gè)獨(dú)立的導(dǎo)出

// bad
import * as AirbnbStyleGuide from "./AirbnbStyleGuide";

// good
import AirbnbStyleGuide from "./AirbnbStyleGuide";

不要把導(dǎo)入和導(dǎo)出寫(xiě)在一起,雖然一行簡(jiǎn)明扼要,但是我們更需要明確的導(dǎo)入方式和導(dǎo)出方式,保持其一致性

// bad
// filename es6.js
export { es6 as default } from "./AirbnbStyleGuide";

// good
// filename es6.js
import { es6 } from "./AirbnbStyleGuide";
export default es6;

一個(gè)路徑一次支持一個(gè)導(dǎo)入,因?yàn)橐粋€(gè)路徑一次支持有多個(gè)導(dǎo)入,會(huì)使代碼變得難以維護(hù)

// bad
import foo from "foo";
// … some other imports … //
import { named1, named2 } from "foo";

// good
import foo, { named1, named2 } from "foo";

// good
import foo, {
  named1,
  named2,
} from "foo";

拒絕導(dǎo)出可變綁定,這種方式通常應(yīng)該避免,但是不排除有某些特殊情況需要這么做,但是應(yīng)該記住,通常只導(dǎo)出常量引用

// bad
let foo = 3;
export { foo };
 
// good
const foo = 3;
export { foo };

在具有單一導(dǎo)出的模塊中,建議使用默認(rèn)導(dǎo)出而不是命名導(dǎo)出,這樣對(duì)于代碼的可讀性和可維護(hù)性更加友好

// bad
export function foo() {}

// good
export default function foo() {}

把所有的導(dǎo)入語(yǔ)句放在一起

// bad
import foo from "foo";
foo.init();

import bar from "bar";

// good
import foo from "foo";
import bar from "bar";

foo.init();

多行導(dǎo)入應(yīng)該項(xiàng)多行數(shù)組和對(duì)象一樣縮進(jìn),這樣保持 {} 內(nèi)容的一致性

// bad
import {longNameA, longNameB, longNameC, longNameD, longNameE} from "path";

// good
import {
  longNameA,
  longNameB,
  longNameC,
  longNameD,
  longNameE,
} from "path";

導(dǎo)出語(yǔ)句中不允許出現(xiàn) webpack 加載器語(yǔ)法。因?yàn)閷?dǎo)入中使用加載器語(yǔ)法會(huì)將代碼耦合到模塊打包器中,,更建議使用 webpack.config.js

// bad
import fooSass from "css!sass!foo.scss";
import barCss from "style!css!bar.css";

// good
import fooSass from "foo.scss";
import barCss from "bar.css";
Iterators and Generators(迭代器和發(fā)生器)

不要使用迭代器,更推薦使用javascript的高階方法而不是 for-infor-of 這些。使用 map()every()filter()find()findIndex()reduce()some() 等遍歷數(shù)組,以及Object.keys()Object.values()Object.entries()去生成數(shù)組,以便迭代對(duì)象。因?yàn)樘幚矸祷刂档募兒瘮?shù)更容易定位問(wèn)題

const numbers = [1, 2, 3, 4, 5];

// bad
let sum = 0;
for (let num of numbers) {
  sum += num;
}
sum === 15;

// good
let sum = 0;
numbers.forEach((num) => {
  sum += num;
});
sum === 15;

// best (use the functional force)
const sum = numbers.reduce((total, num) => total + num, 0);
sum === 15;

// bad
const increasedByOne = [];
for (let i = 0; i < numbers.length; i++) {
  increasedByOne.push(numbers[i] + 1);
}

// good
const increasedByOne = [];
numbers.forEach((num) => {
  increasedByOne.push(num + 1);
});

// best (keeping it functional)
const increasedByOne = numbers.map(num => num + 1);

不要使用發(fā)生器,因?yàn)樗麄冞€沒(méi)有很好的兼容

如果你一定要用發(fā)生器,一定要注意關(guān)鍵字符的間距,舉個(gè)例子,function* 是一個(gè)不同于 function 的獨(dú)特構(gòu)造,并且 *是其構(gòu)造的一部分

// bad
function * foo() {
  // ...
}

// bad
const bar = function * () {
  // ...
};

// bad
const baz = function *() {
  // ...
};
 
// bad
const quux = function*() {
  // ...
};

// bad
function*foo() {
  // ...
}

// bad
function *foo() {
  // ...
}

// very bad
function*
foo() {
  // ...
}
  
// very bad
const wat = function*
() {
  // ...
};

// good
function* foo() {
  // ...
}

// good
const foo = function* () {
  // ...
};
Properties(屬性)

通過(guò)常量訪(fǎng)問(wèn)屬性的時(shí)候使用 .

const luke = {
  jedi: true,
  age: 28,
};

// bad
const isJedi = luke["jedi"];

// good
const isJedi = luke.jedi;

通過(guò)變量訪(fǎng)問(wèn)屬性的時(shí)候用 []

const luke = {
  jedi: true,
  age: 28,
};

function getProp(prop) {
  return luke[prop];
}

const isJedi = getProp("jedi");

使用 ** 進(jìn)行指數(shù)運(yùn)算

// bad
const binary = Math.pow(2, 10);

// good
const binary = 2 ** 10;
Variables(變量)

總是使用 const 或者 let 來(lái)聲明變量,這樣做可以避免污染全局命名空間

// bad
superPower = new SuperPower();

// good
const superPower = new SuperPower();

每個(gè)變量聲明都對(duì)應(yīng)一個(gè) const 或者 let。這樣做,可以獨(dú)立的聲明每一個(gè)變量,而不需要考慮 ;,的關(guān)系,同時(shí)也方便對(duì)每個(gè)聲明進(jìn)行調(diào)試,而不是跳過(guò)所有的聲明

// bad
const items = getItems(),
    goSportsTeam = true,
    dragonball = "z";
  
// bad
// (compare to above, and try to spot the mistake)
const items = getItems(),
    goSportsTeam = true;
    dragonball = "z";
      
// good
const items = getItems();
const goSportsTeam = true;
const dragonball = "z";

對(duì) letconst 進(jìn)行分組,這樣增強(qiáng)代碼可讀性

// bad
let i, len, dragonball,
    items = getItems(),
    goSportsTeam = true;
 
// bad
let i;
const items = getItems();
let dragonball;
const goSportsTeam = true;
let len;
  
// good
const goSportsTeam = true;
const items = getItems();
let dragonball;
let i;
let length;

在需要的地方聲明變量,因?yàn)?constlet 是塊作用域而不是函數(shù)作用域

// bad - unnecessary function call
function checkName(hasName) {
  const name = getName();

  if (hasName === "test") {
    return false;
  }

  if (name === "test") {
    this.setName("");
    return false;
  }

  return name;
}

// good
function checkName(hasName) {
  if (hasName === "test") {
    return false;
  }

  const name = getName();

  if (name === "test") {
    this.setName("");
    return false;
  }

  return name;
}

不要進(jìn)行鏈?zhǔn)铰暶髯兞康牟僮鳎@樣可能創(chuàng)建隱式的全局變量

// bad
(function example() {
  // JavaScript interprets this as
  // let a = ( b = ( c = 1 ) );
  // The let keyword only applies to variable a; variables b and c become
  // global variables.
  let a = b = c = 1;
}());

console.log(a); // throws ReferenceError
console.log(b); // 1
console.log(c); // 1

// good
(function example() {
  let a = 1;
  let b = a;
  let c = a;
}());

console.log(a); // throws ReferenceError
console.log(b); // throws ReferenceError
console.log(c); // throws ReferenceError
  
// the same applies for `const`

不要使用一元遞增和遞減操作符(++,--),因?yàn)橐辉f增和一元遞減可能受到分號(hào)插入的影響,并且可能導(dǎo)致應(yīng)用中的值遞增或者遞減,并且不會(huì)報(bào)錯(cuò)。使用 num += 1 類(lèi)似的語(yǔ)句也更加有表現(xiàn)力,并且可以避免預(yù)先遞增或者遞減從而導(dǎo)致程序發(fā)生意外

// bad
const array = [1, 2, 3];
let num = 1;
num++;
--num;
  
let sum = 0;
let truthyCount = 0;
for (let i = 0; i < array.length; i++) {
  let value = array[i];
  sum += value;
  if (value) {
    truthyCount++;
  }
}
  
// good
const array = [1, 2, 3];
let num = 1;
num += 1;
num -= 1;
  
const sum = array.reduce((a, b) => a + b, 0);
const truthyCount = array.filter(Boolean).length;
```                          
Hoisting(變量提升)

var 聲明被置于函數(shù)作用域的頂部,但是他們的賦值不是, constlet聲明會(huì)被置于一個(gè)新概念TDZ內(nèi)。因此, typeof() 方法不再安全

// we know this wouldn’t work (assuming there
// is no notDefined global variable)
function example() {
  console.log(notDefined); // => throws a ReferenceError
}

// creating a variable declaration after you
// reference the variable will work due to
// variable hoisting. Note: the assignment
// value of `true` is not hoisted.
function example() {
  console.log(declaredButNotAssigned); // => undefined
  var declaredButNotAssigned = true;
}

// the interpreter is hoisting the variable
// declaration to the top of the scope,
// which means our example could be rewritten as:
function example() {
  let declaredButNotAssigned;
  console.log(declaredButNotAssigned); // => undefined
  declaredButNotAssigned = true;
}

// using const and let
function example() {
  console.log(declaredButNotAssigned); // => throws a ReferenceError
  console.log(typeof declaredButNotAssigned); // => throws a ReferenceError
  const declaredButNotAssigned = true;
}

匿名函數(shù)表達(dá)式會(huì)提升變量名,而不是函數(shù)賦值

function example() {
  console.log(anonymous); // => undefined

  anonymous(); // => TypeError anonymous is not a function

  var anonymous = function () {
    console.log("anonymous function expression");
  };
}

命名函數(shù)表達(dá)式提升變量名,而不是函數(shù)名或者函數(shù)體

function example() {
  console.log(named); // => undefined

  named(); // => TypeError named is not a function

  superPower(); // => ReferenceError superPower is not defined

  var named = function superPower() {
    console.log("Flying");
  };
}

// the same is true when the function name
// is the same as the variable name.
function example() {
  console.log(named); // => undefined

  named(); // => TypeError named is not a function

  var named = function named() {
    console.log("named");
  };
}

函數(shù)聲明提升其名字和函數(shù)體

function example() {
  superPower(); // => Flying

  function superPower() {
    console.log("Flying");
  }
}
Comparison Operators & Equality(比較操作符和等號(hào))

使用 ===,!== 取代 ==,!=

條件語(yǔ)句比如 if 會(huì)強(qiáng)制使用 ToBoolean 抽象方法來(lái)進(jìn)行轉(zhuǎn)換,并且遵循以下規(guī)則:

Objects 轉(zhuǎn)換為 true

Undefined 轉(zhuǎn)換為 false

Null 轉(zhuǎn)換為 false

Booleans 轉(zhuǎn)換為 the value of the boolean

Numbers 轉(zhuǎn)換為 false 如果是 +0, -0, or NaN, 其余為 true

Strings 轉(zhuǎn)換為 false 如果是空字符串 "", 其余為 true

if ([0] && []) {
  // true
  // an array (even an empty one) is an object, objects will evaluate to true
}

使用布爾值的快捷比較方式,但是顯示比較字符串和數(shù)字

// bad
if (isValid === true) {
  // ...
}

// good
if (isValid) {
  // ...
}

// bad
if (name) {
  // ...
}

// good
if (name !== "") {
  // ...
}

// bad
if (collection.length) {
  // ...
}

// good
if (collection.length > 0) {
  // ...
}

switch 語(yǔ)句中的 casedefault 使用 {} 來(lái)創(chuàng)建塊,比如let, const, function, class 也是如此。因?yàn)樵谡麄€(gè) switch 塊中詞法聲明是隨處可見(jiàn)的,但是只有在賦值時(shí)才會(huì)被初始化,且只有 case 值達(dá)到時(shí)才會(huì)發(fā)生。但是當(dāng)多個(gè) case 子句試圖定義相同的東西時(shí),就會(huì)發(fā)生問(wèn)題

// bad
switch (foo) {
  case 1:
    let x = 1;
    break;
  case 2:
    const y = 2;
    break;
  case 3:
    function f() {
      // ...
    }
    break;
  default:
    class C {}
}

// good
switch (foo) {
  case 1: {
    let x = 1;
    break;
  }
  case 2: {
    const y = 2;
    break;
  }
  case 3: {
    function f() {
      // ...
    }
    break;
  }
  case 4:
    bar();
    break;
  default: {
    class C {}
  }
}

三元表達(dá)式不應(yīng)該嵌套,而應(yīng)該單行表達(dá)

// bad
const foo = maybe1 > maybe2
  ? "bar"
  : value1 > value2 ? "baz" : null;

// split into 2 separated ternary expressions
const maybeNull = value1 > value2 ? "baz" : null;

// better
const foo = maybe1 > maybe2
  ? "bar"
  : maybeNull;

// best
const foo = maybe1 > maybe2 ? "bar" : maybeNull;

沒(méi)事不要隨便用三元表達(dá)式

// bad
const foo = a ? a : b;
const bar = c ? true : false;
const baz = c ? false : true;

// good
const foo = a || b;
const bar = !!c;
const baz = !c;

當(dāng)多個(gè)運(yùn)算符混在一個(gè)語(yǔ)句中時(shí),將需要的運(yùn)算符括在括號(hào)里面,并且用括號(hào)區(qū)分開(kāi) **,%+,-,*,/,這樣代碼更加有可讀性,并且澄清了開(kāi)發(fā)者的意圖

// bad
const foo = a && b < 0 || c > 0 || d + 1 === 0;

// bad
const bar = a ** b - 5 % d;

// bad
// one may be confused into thinking (a || b) && c
if (a || b && c) {
  return d;
}
 
// good
const foo = (a && b < 0) || c > 0 || (d + 1 === 0);

// good
const bar = (a ** b) - (5 % d);

// good
if (a || (b && c)) {
  return d;
}

// good
const bar = a + b / c * d;
Blocks(塊)

所有的多行塊都要用 {}

// bad
if (test)
  return false;

// good
if (test) return false;

// good
if (test) {
  return false;
}

// bad
function foo() { return false; }

// good
function bar() {
  return false;
}

如果使用 if else, else 需要和 if} 在同一行

// bad
if (test) {
  thing1();
  thing2();
}
else {
  thing3();
}

// good
if (test) {
  thing1();
  thing2();
} else {
  thing3();
}

如果一個(gè) if else 語(yǔ)句內(nèi)每個(gè)代碼塊都用了 return 語(yǔ)句,那么 else 語(yǔ)句就沒(méi)有必要,分成多個(gè) if 語(yǔ)句就行了

// bad
function foo() {
  if (x) {
    return x;
  } else {
    return y;
  }
}

// bad
function cats() {
  if (x) {
    return x;
  } else if (y) {
    return y;
  }
}
 
// bad
function dogs() {
  if (x) {
    return x;
  } else {
    if (y) {
      return y;
    }
  }
}

// good
function foo() {
  if (x) {
    return x;
  }

  return y;
}

// good
function cats() {
  if (x) {
    return x;
  }

  if (y) {
    return y;
  }
}
 
//good
function dogs(x) {
  if (x) {
    if (z) {
      return y;
    }
  } else {
    return z;
  }
}
Control Statements(控制語(yǔ)句)

如果你的控制語(yǔ)句,比如 if,while等很長(zhǎng),或者超過(guò)了行寬,你可以對(duì)其中的內(nèi)容進(jìn)行換行,但是需要注意,邏輯運(yùn)算符需要放在行首

// bad
if ((foo === 123 || bar === "abc") && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) {
  thing1();
}

// bad
if (foo === 123 &&
  bar === "abc") {
  thing1();
}

// bad
if (foo === 123
  && bar === "abc") {
  thing1();
}

// bad
if (
  foo === 123 &&
  bar === "abc"
) {
  thing1();
}

// good
if (
  foo === 123
  && bar === "abc"
) {
  thing1();
}

// good
if (
  (foo === 123 || bar === "abc")
  && doesItLookGoodWhenItBecomesThatLong()
  && isThisReallyHappening()
) {
  thing1();
}

// good
if (foo === 123 && bar === "abc") {
  thing1();
}
Comments(注釋?zhuān)?/b>

多行注釋使用 /** ... */

// bad
// make() returns a new element
// based on the passed in tag name
//
// @param {String} tag
// @return {Element} element
function make(tag) {
    
  // ...
    
  return element;
}
 
// good
/**
 * make() returns a new element
 * based on the passed-in tag name
 */
    function make(tag) {
 
  // ...
 
  return element;
}

單行注釋用 //,并且在注釋內(nèi)容的上一行,在注釋語(yǔ)句之前要空一行,當(dāng)然,如果注釋在文件的第一行就不需要空行了

// bad
const active = true;  // is current tab

// good
// is current tab
const active = true;

// bad
function getType() {
  console.log("fetching type...");
  // set the default type to "no type"
  const type = this.type || "no type";

  return type;
}

// good
function getType() {
  console.log("fetching type...");

  // set the default type to "no type"
  const type = this.type || "no type";
  return type;
}

// also good
function getType() {
  // set the default type to "no type"
  const type = this.type || "no type";
  return type;
}

注釋文字以空格作為開(kāi)始,方便閱讀

// bad
//is current tab
const active = true;
  
// good
// is current tab
const active = true;
  
// bad
/**
 *make() returns a new element
 *based on the passed-in tag name
 */
function make(tag) {
  
  // ...
  
  return element;
}
  
// good
/**
 * make() returns a new element
 * based on the passed-in tag name
 */
function make(tag) {
  
  // ...
  
  return element;
}

 - 為你的提交或者評(píng)論加上 `FIXME` 或者 `TODO` 的前綴,好讓其他開(kāi)發(fā)者迅速明白你的意思。 `FIXME`表示這個(gè)問(wèn)題需要弄清楚,`TODO`表示這個(gè)問(wèn)題需要解決

 - 使用 `// FIXME` 去注釋問(wèn)題

class Calculator extends Abacus {
  constructor() {
    super();

    // FIXME: shouldn’t use a global here
    total = 0;
  }
}
```

使用 // TODO 去注釋問(wèn)題的解決方法

class Calculator extends Abacus {
  constructor() {
    super();
  
    // TODO: total should be configurable by an options param
    this.total = 0;
  }
}
Whitespace(空格)

使用 tab 去設(shè)置兩個(gè)空格

// bad
function foo() {
????let name;
}

// bad
function bar() {
?let name;
}

// good
function baz() {
??let name;
}

使用 {} 之前空一格

// bad
function test(){
  console.log("test");
}

// good
function test() {
  console.log("test");
}

// bad
dog.set("attr",{
  age: "1 year",
  breed: "Bernese Mountain Dog",
});

// good
dog.set("attr", {
  age: "1 year",
  breed: "Bernese Mountain Dog",
});

判斷語(yǔ)句(if,while)左括號(hào)之前加一個(gè)空格,在函數(shù)聲明,函數(shù)調(diào)用,參數(shù)列表的 () 不需要空格

// bad
if(isJedi) {
  fight ();
}

// good
if (isJedi) {
  fight();
}

// bad
function fight () {
  console.log ("Swooosh!");
}

// good
function fight() {
  console.log("Swooosh!");
}

操作符之間要加空格

// bad
const x=y+5;

// good
const x = y + 5;

文件導(dǎo)出通過(guò)換行符結(jié)束

// bad
import { es6 } from "./AirbnbStyleGuide";
  // ...
export default es6;
// bad
import { es6 } from "./AirbnbStyleGuide";
  // ...
export default es6;?
?
// good
import { es6 } from "./AirbnbStyleGuide";
  // ...
export default es6;?

如果寫(xiě)一個(gè)長(zhǎng)的方法鏈(連續(xù)使用超過(guò)三個(gè)方法)時(shí),使用縮進(jìn)來(lái)表示層級(jí)關(guān)系。使用前導(dǎo)點(diǎn)來(lái)表示該行是一個(gè)方法調(diào)用而不是一個(gè)新的語(yǔ)句

// bad
$("#items").find(".selected").highlight().end().find(".open").updateCount();

// bad
$("#items").
  find(".selected").
    highlight().
    end().
  find(".open").
    updateCount();

// good
$("#items")
  .find(".selected")
    .highlight()
    .end()
  .find(".open")
    .updateCount();

// bad
const leds = stage.selectAll(".led").data(data).enter().append("svg:svg").classed("led", true)
    .attr("width", (radius + margin) * 2).append("svg:g")
    .attr("transform", `translate(${radius + margin},${radius + margin})`)
    .call(tron.led);

// good
const leds = stage.selectAll(".led")
    .data(data)
  .enter().append("svg:svg")
    .classed("led", true)
    .attr("width", (radius + margin) * 2)
  .append("svg:g")
    .attr("transform", `translate(${radius + margin},${radius + margin})`)
    .call(tron.led);

// good
const leds = stage.selectAll(".led").data(data);

塊與塊,塊與語(yǔ)句之間需要空一行

// bad
if (foo) {
  return bar;
}
return baz;

// good
if (foo) {
  return bar;
}

return baz;

// bad
const obj = {
  foo() {
  },
  bar() {
  },
};
return obj;

// good
const obj = {
  foo() {
  },

  bar() {
  },
};

return obj;

// bad
const arr = [
  function foo() {
  },
  function bar() {
  },
];
return arr;

// good
const arr = [
  function foo() {
  },

  function bar() {
  },
];

return arr;

塊內(nèi)不要空行

// bad
function bar() {

  console.log(foo);

}

// bad
if (baz) {

  console.log(qux);
} else {
  console.log(foo);

}

// bad  
class Foo {

  constructor(bar) {
    this.bar = bar;
  }
}

// good
function bar() {
  console.log(foo);
}

// good
if (baz) {
  console.log(qux);
} else {
  console.log(foo);
}

() 里面不要加空格

// bad
function bar( foo ) {
  return foo;
}

// good
function bar(foo) {
  return foo;
}

// bad
if ( foo ) {
  console.log(foo);
}

// good
if (foo) {
  console.log(foo);
}

[] 不要隨意加空格

// bad
const foo = [ 1, 2, 3 ];
console.log(foo[ 0 ]);

// good
const foo = [1, 2, 3];
console.log(foo[0]);

{} 里面要加空格

// bad
const foo = {clark: "kent"};

// good
const foo = { clark: "kent" };

除了之前提到的長(zhǎng)字符串,避免出現(xiàn)一行代碼超過(guò)100個(gè)字符的情況,這樣確保了可維護(hù)性和可讀性

// bad
const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy;

// bad
$.ajax({ method: "POST", url: "https://airbnb.com/", data: { name: "John" } }).done(() => console.log("Congratulations!")).fail(() => console.log("You have failed this city."));

// good
const foo = jsonData
  && jsonData.foo
  && jsonData.foo.bar
  && jsonData.foo.bar.baz
  && jsonData.foo.bar.baz.quux
  && jsonData.foo.bar.baz.quux.xyzzy;

// good
$.ajax({
  method: "POST",
  url: "https://airbnb.com/",
  data: { name: "John" },
})
  .done(() => console.log("Congratulations!"))
  .fail(() => console.log("You have failed this city."));
Commas(逗號(hào))

逗號(hào)不要放在行首

// bad
const story = [
    once
  , upon
  , aTime
];

// good
const story = [
  once,
  upon,
  aTime,
];

// bad
const hero = {
    firstName: "Ada"
  , lastName: "Lovelace"
  , birthYear: 1815
  , superPower: "computers"
};

// good
const hero = {
  firstName: "Ada",
  lastName: "Lovelace",
  birthYear: 1815,
  superPower: "computers",
};

有時(shí)需要附加的逗號(hào),一是為了在 git 上能保持一致,因?yàn)?git 在增減之后都會(huì)帶上逗號(hào),二是一些像Babel這樣的轉(zhuǎn)譯器會(huì)自動(dòng)刪除不必要的逗號(hào),這意味著不必?fù)?dān)心傳統(tǒng)瀏覽器中的逗號(hào)尾隨問(wèn)題

// bad - git diff without trailing comma
const hero = {
     firstName: "Florence",
-    lastName: "Nightingale"
+    lastName: "Nightingale",
+    inventorOf: ["coxcomb chart", "modern nursing"]
};
 
// good - git diff with trailing comma
const hero = {
     firstName: "Florence",
     lastName: "Nightingale",
+    inventorOf: ["coxcomb chart", "modern nursing"],
};
  
// bad
const hero = {
  firstName: "Dana",
  lastName: "Scully"
};
  
const heroes = [
  "Batman",
  "Superman"
];
  
// good
const hero = {
  firstName: "Dana",
  lastName: "Scully",
};
  
const heroes = [
  "Batman",
  "Superman",
];
  
// bad
function createHero(
  firstName,
  lastName,
  inventorOf
) {
  // does nothing
}
  
// good
function createHero(
  firstName,
  lastName,
  inventorOf,
) {
  // does nothing
}
  
// good (note that a comma must not appear after a "rest" element)
function createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
) {
  // does nothing
}
  
// bad
createHero(
  firstName,
  lastName,
  inventorOf
);
  
// good
createHero(
  firstName,
  lastName,
  inventorOf,
);
  
// good (note that a comma must not appear after a "rest" element)
createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
);
Semicolons(分號(hào))

在代碼的結(jié)尾一定要用 ; 結(jié)尾,防止javascript的自動(dòng)分號(hào)插入機(jī)制使整個(gè)程序報(bào)錯(cuò)

// bad - raises exception
const luke = {}
const leia = {}
[luke, leia].forEach(jedi => jedi.father = "vader")

// bad - raises exception
const reaction = "No! That"s impossible!"
(async function meanwhileOnTheFalcon(){
  // handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
  // ...
}())

// bad - returns `undefined` instead of the value on the next line - always happens when `return` is on a line by itself because of ASI!
function foo() {
  return
    "search your feelings, you know it to be foo"
}

// good
const luke = {};
const leia = {};
[luke, leia].forEach((jedi) => {
  jedi.father = "vader";
});

// good
const reaction = "No! That"s impossible!";
(async function meanwhileOnTheFalcon(){
  // handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
  // ...
}());

// good
function foo() {
  return "search your feelings, you know it to be foo";
}
Type Casting & Coercion(強(qiáng)制類(lèi)型轉(zhuǎn)換)

在語(yǔ)句開(kāi)始進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換

String 類(lèi)型

// => this.reviewScore = 9;

// bad
const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string"

// bad
const totalScore = this.reviewScore + ""; // invokes this.reviewScore.valueOf()

// bad
const totalScore = this.reviewScore.toString(); // isn’t guaranteed to return a string

// good
const totalScore = String(this.reviewScore);

Number 類(lèi)型,用 Number 或者 parseInt 進(jìn)行強(qiáng)制轉(zhuǎn)換,通常 parseInt 需要一個(gè)基數(shù)來(lái)解析字符串

const inputValue = "4";

// bad
const val = new Number(inputValue);

// bad
const val = +inputValue;

// bad
const val = inputValue >> 0;

// bad
const val = parseInt(inputValue);

// good
const val = Number(inputValue);

// good
const val = parseInt(inputValue, 10);

如果 parseInt 是你代碼的瓶頸,你不得不使用移位符來(lái)進(jìn)行轉(zhuǎn)換時(shí),一定要在注釋里面說(shuō)明

// good
/**
 * parseInt was the reason my code was slow.
 * Bitshifting the String to coerce it to a
 * Number made it a lot faster.
 */
const val = inputValue >> 0;

使用移位操作符時(shí)需要注意,數(shù)字可以表示為64位,但是移位操作符始終返回32位的源,對(duì)于大于32位的整數(shù),移位操作可能會(huì)導(dǎo)致意外發(fā)生。最大的32位支持是 2,147,483,647

2147483647 >> 0; // => 2147483647
2147483648 >> 0; // => -2147483648
2147483649 >> 0; // => -2147483647

Booleans 類(lèi)型

const age = 0;

// bad
const hasAge = new Boolean(age);

// good
const hasAge = Boolean(age);

// best
const hasAge = !!age;
Naming Conventions(命名協(xié)議)

避免使用單字符命名,注意命名描述

// bad
function q() {
  // ...
}

// good
function query() {
  // ...
}

命名對(duì)象,函數(shù)和實(shí)例時(shí)都使用駝峰命名

// bad
const OBJEcttsssss = {};
const this_is_my_object = {};
function c() {}

// good
const thisIsMyObject = {};
function thisIsMyFunction() {}

對(duì)命名對(duì)象和構(gòu)造函數(shù)時(shí)使用帕斯卡命名

// bad
function user(options) {
  this.name = options.name;
}

const bad = new user({
  name: "nope",
});

// good
class User {
  constructor(options) {
    this.name = options.name;
  }
}

const good = new User({
  name: "yup",
});

頭部,尾部不要使用下劃線(xiàn),因?yàn)镴avaScript的屬性或者方法沒(méi)有隱私的概念。前導(dǎo)下?lián)Q線(xiàn)是一個(gè)常見(jiàn)的慣例,表示“私人”,事實(shí)上,這些屬性是完全公開(kāi)的,這樣會(huì)讓人產(chǎn)生誤解

// bad
this.__firstName__ = "Panda";
this.firstName_ = "Panda";
this._firstName = "Panda";

// good
this.firstName = "Panda";

不要保存 this 指針,使用箭頭函數(shù)或者 # 綁定來(lái)取代

// bad
function foo() {
  const self = this;
  return function () {
    console.log(self);
  };
}

// bad
function foo() {
  const that = this;
  return function () {
    console.log(that);
  };
}

// good
function foo() {
  return () => {
    console.log(this);
  };
}

基本文件名應(yīng)該與其導(dǎo)出名字對(duì)應(yīng)

// file 1 contents
class CheckBox {
  // ...
}
export default CheckBox;

// file 2 contents
export default function fortyTwo() { return 42; }

// file 3 contents
export default function insideDirectory() {}

// in some other file
// bad
import CheckBox from "./checkBox"; // PascalCase import/export, camelCase filename
import FortyTwo from "./FortyTwo"; // PascalCase import/filename, camelCase export
import InsideDirectory from "./InsideDirectory"; // PascalCase import/filename, camelCase export

// bad
import CheckBox from "./check_box"; // PascalCase import/export, snake_case filename
import forty_two from "./forty_two"; // snake_case import/filename, camelCase export
import inside_directory from "./inside_directory"; // snake_case import, camelCase export
import index from "./inside_directory/index"; // requiring the index file explicitly
import insideDirectory from "./insideDirectory/index"; // requiring the index file explicitly

// good
import CheckBox from "./CheckBox"; // PascalCase export/import/filename
import fortyTwo from "./fortyTwo"; // camelCase export/import/filename
import insideDirectory from "./insideDirectory"; // camelCase export/import/directory name/implicit "index"
// ^ supports both insideDirectory.js and insideDirectory/index.js

默認(rèn)導(dǎo)出一個(gè)方法時(shí),使用駝峰命名表示。同時(shí),你的文件名應(yīng)該與方法名一致

function makeStyleGuide() {
  // ...
}

export default makeStyleGuide;

導(dǎo)出構(gòu)造函數(shù),類(lèi),單例,函數(shù)庫(kù)等時(shí),使用帕斯卡命名

const AirbnbStyleGuide = {
  es6: {
  },
};

export default AirbnbStyleGuide;

縮略詞應(yīng)該全是大小字母或者全是小寫(xiě)字母構(gòu)成,這樣才有可讀性

// bad
import SmsContainer from "./containers/SmsContainer";

// bad
const HttpRequests = [
  // ...
];

// good
import SMSContainer from "./containers/SMSContainer";

// good
const HTTPRequests = [
  // ...
];

// also good
const httpRequests = [
  // ...
];

// best
import TextMessageContainer from "./containers/TextMessageContainer";

// best
const requests = [
  // ...
];
Accessors(訪(fǎng)問(wèn)方法)

屬性的訪(fǎng)問(wèn)方法不是必須的

不要使用JavaScript的 getters/setters,因?yàn)樗鼈儠?huì)造成意想不到的壞的影響,并且很難去測(cè)試,定位。所以如果你要用訪(fǎng)問(wèn)函數(shù),使用 getVal()setVal() 這樣的方式

// bad
class Dragon {
  get age() {
    // ...
  }

  set age(value) {
    // ...
  }
}

// good
class Dragon {
  getAge() {
    // ...
  }

  setAge(value) {
    // ...
  }
}

如果一個(gè)屬性值或者方法返回值是布爾類(lèi)型,使用 isVal()或者 hasVal()這樣的形式

// bad
if (!dragon.age()) {
  return false;
}

// good
if (!dragon.hasAge()) {
  return false;
}

可以創(chuàng)建類(lèi)似 get()set() 這樣的函數(shù)方法,但是要注意保持一致

class Jedi {
  constructor(options = {}) {
    const lightsaber = options.lightsaber || "blue";
    this.set("lightsaber", lightsaber);
  }

  set(key, val) {
    this[key] = val;
  }

  get(key) {
    return this[key];
  }
}
Events(事件)

當(dāng)將數(shù)據(jù)傳遞到事件方法里面的時(shí)候,不要使用原始值直接進(jìn)行傳遞,應(yīng)該處理成對(duì)象字面量。這樣可以方便其他用戶(hù)修改或者查看傳遞數(shù)據(jù)

// bad
$(this).trigger("listingUpdated", listing.id);
// ...
$(this).on("listingUpdated", (e, listingId) => {
  // do something with listingId
});

// good
$(this).trigger("listingUpdated", { listingId: listing.id });
// ...
$(this).on("listingUpdated", (e, data) => {
  // do something with data.listingId
});
jQuery

通過(guò) $ 來(lái)聲明一個(gè)承載jquery的元素

// bad
const sidebar = $(".sidebar");

// good
const $sidebar = $(".sidebar");

// good
const $sidebarBtn = $(".sidebar-btn");

將jquery選擇器緩存起來(lái)

// bad
function setSidebar() {
  $(".sidebar").hide();

  // ...

  $(".sidebar").css({
    "background-color": "pink",
  });
}

// good
function setSidebar() {
  const $sidebar = $(".sidebar");
  $sidebar.hide();

  // ...

  $sidebar.css({
    "background-color": "pink",
  });
}

對(duì)于 DOM 節(jié)點(diǎn)的查詢(xún)使用級(jí)聯(lián) $(".sidebar ul") 或者 父級(jí) > 子級(jí) $(".sidebar > ul")

塊級(jí)jQuery對(duì)象查詢(xún)(通過(guò)選擇器對(duì)象進(jìn)行查詢(xún)),使用 find

// bad
$("ul", ".sidebar").hide();

// bad
$(".sidebar").find("ul").hide();

// good
$(".sidebar ul").hide();

// good
$(".sidebar > ul").hide();

// good
$sidebar.find("ul").hide();
Standard Library(標(biāo)準(zhǔn)程序庫(kù))

使用 Number.isNaN 來(lái)代替全局的 isNaN,因?yàn)槿值?isNaN 會(huì)強(qiáng)制將非數(shù)字類(lèi)型轉(zhuǎn)換為數(shù)字類(lèi)型,任何強(qiáng)制轉(zhuǎn)換為非數(shù)字的都會(huì)返回true

// bad
isNaN("1.2"); // false
isNaN("1.2.3"); // true

// good
Number.isNaN("1.2.3"); // false
Number.isNaN(Number("1.2.3")); // true

使用 Number.isFinite 來(lái)代替全局的 isFinite,因?yàn)槿值?isFinite 會(huì)強(qiáng)制將非數(shù)字類(lèi)型轉(zhuǎn)換為數(shù)字類(lèi)型,任何強(qiáng)制轉(zhuǎn)換為有限數(shù)字的結(jié)果都會(huì)返回true

// bad
isFinite("2e3"); // true

// good
Number.isFinite("2e3"); // false
Number.isFinite(pa           
               
                                           
                       
                 

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/92538.html

相關(guān)文章

  • 在 React-CRA 應(yīng)用中配合 VSCode 使用 ESLint 實(shí)踐前端代碼規(guī)范

    摘要:編碼規(guī)范是獨(dú)角獸公司內(nèi)部的編碼規(guī)范,該項(xiàng)目是上很受歡迎的一個(gè)開(kāi)源項(xiàng)目,在前端開(kāi)發(fā)中使用廣泛,本文的配置規(guī)則就是以編碼規(guī)范和編碼規(guī)范作為基礎(chǔ)的。 更新時(shí)間:2019-01-22React.js create-react-app 項(xiàng)目 + VSCode 編輯器 + ESLint 代碼檢查工具 + Airbnb 編碼規(guī)范 前言 為什么要使用 ESLint 在項(xiàng)目開(kāi)發(fā)過(guò)程中,編寫(xiě)符合團(tuán)隊(duì)編碼規(guī)...

    Hujiawei 評(píng)論0 收藏0
  • JavaScript代碼注釋范例

    摘要:包含描述與指定所有參數(shù)和返回值的類(lèi)型和值的注釋標(biāo)簽。返回值的類(lèi)型和描述或者更多示例更多請(qǐng)參考以下網(wǎng)站為本文參考,歡迎留言糾正。注解注釋原文代碼注釋規(guī)范與示例注釋 JavaScript代碼注釋范例 做為一個(gè)有情懷的Coder,最近收集了一下JavaScript代碼注釋范例,希望能夠幫助大家擼得一手妖媚而又放蕩的Bug。 普通注釋 單行注釋 使用 // 作為單行注釋。 單行注釋符后與注釋內(nèi)...

    int64 評(píng)論0 收藏0
  • 大規(guī)模應(yīng)用TypeScript「2019 JSConf -Brie Bunge」

    摘要:眾所周知,在大公司中進(jìn)行大的改革很難。目前公司有超過(guò)名開(kāi)發(fā)人員,其中有個(gè)以上是前端。從年起,已經(jīng)在一些小規(guī)模團(tuán)隊(duì)中探索使用。在年的前端調(diào)查中,靜態(tài)類(lèi)型系統(tǒng)呼聲最高。在我們的主倉(cāng)庫(kù)中,絕大多數(shù)的公共依賴(lài)都已經(jīng)由做到了類(lèi)型聲明。 特別說(shuō)明 這是一個(gè)由simviso團(tuán)隊(duì)進(jìn)行的關(guān)于A(yíng)irbnb大規(guī)模應(yīng)用TypeScript分享的翻譯文檔,分享者是Airbnb的高級(jí)前端開(kāi)發(fā)Brie Bunge ...

    qpal 評(píng)論0 收藏0
  • 我不能再忍受你的代碼風(fēng)格了!——JSCS

    摘要:從來(lái)沒(méi)有見(jiàn)過(guò)這么強(qiáng)大的代碼格式化和風(fēng)格統(tǒng)一工具。你可以預(yù)設(shè)像等公司的代碼風(fēng)格。所有工具的安裝辦法自動(dòng)生成你的代碼風(fēng)格的配置文件。學(xué)會(huì)的代碼規(guī)范,意味著你的代碼風(fēng)格已經(jīng)走在了世界第一行列。 無(wú)論人數(shù)多少,代碼都應(yīng)該同出一門(mén)。 JavaScript 或者 Node 的語(yǔ)法本身很弱,在teamwork 和大型項(xiàng)目開(kāi)發(fā)的時(shí)候,技術(shù)選型時(shí)往往選擇了 typescript 或者加入 Faceboo...

    Scott 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<