天天看點

開發規範:Javascript開發規範

  1. 類型
  2. 對象
  3. 數組
  4. 字元串
  5. 函數
  6. 屬性
  7. 變量
  8. 提升
  9. 比較運算符 & 等号
  10. 注釋
  11. 空白
  12. 逗号
  13. 分号
  14. 類型轉化
  15. 命名規則
  16. 存取器
  17. 構造函數
  18. 事件
  19. 子產品
  20. jQuery
  21. ECMAScript 5 相容性
  22. 測試
  23. 性能
  24. 資源
  25. 誰在使用

類     型

  • 原始值: 存取直接作用于它自身。
  • string

  • number

  • boolean

  • null

  • undefined

var

foo = 1;

var

bar = foo;

bar = 9;

console.log(foo, bar); 

// => 1, 9

  • 複雜類型: 存取時作用于它自身值的引用。
  • object

  • array

  • function

var

foo = [1, 2];

var

bar = foo;

bar[0] = 9;

console.log(foo[0], bar[0]); 

// => 9, 9

對象

  • 使用直接量建立對象。

// bad

var

item = 

new

Object();

// good

var

item = {};

  • 不要使用保留字作為鍵名,它們在 IE8 下不工作。

// bad

var

superman = {

default

: { clark: 

'kent'

},

private: 

true

};

// good

var

superman = {

defaults: { clark: 

'kent'

},

hidden: 

true

};

  • 使用同義詞替換需要使用的保留字。

// bad

var

superman = {

class: 

'alien'

};

// bad

var

superman = {

klass: 

'alien'

};

// good

var

superman = {

type: 

'alien'

};

數組

  • 使用直接量建立數組。

// bad

var

items = 

new

Array();

// good

var

items = [];

  • 向數組增加元素時使用 Array#push 來替代直接指派。

var

someStack = [];

// bad

someStack[someStack.length] = 

'abracadabra'

;

// good

someStack.push(

'abracadabra'

);

  • 當你需要拷貝數組時,使用 Array#slice。jsPerf

var

len = items.length;

var

itemsCopy = [];

var

i;

// bad

for

(i = 0; i < len; i++) {

itemsCopy[i] = items[i];

}

// good

itemsCopy = items.slice();

  • 使用 Array#slice 将類數組對象轉換成數組。

function

trigger() {

var

args = Array.prototype.slice.call(arguments);

...

}

字元串

  • 使用單引号 

    ''

     包裹字元串。

// bad

var

name = 

"Bob Parr"

;

// good

var

name = 

'Bob Parr'

;

// bad

var

fullName = 

"Bob "

this

.lastName;

// good

var

fullName = 

'Bob '

this

.lastName;

  • 超過 100 個字元的字元串應該使用連接配接符寫成多行。
  • 注:若過度使用,通過連接配接符連接配接的長字元串可能會影響性能。jsPerf

// bad

var

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

var

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

var

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.'

;

  • 程式化生成的字元串使用 Array#join 連接配接而不是使用連接配接符。尤其是 IE 下:jsPerf.(http://jsperf.com/ya-string-concat)

var

items;

var

messages;

var

length;

var

i;

messages = [{

state: 

'success'

,

message: 

'This one worked.'

}, {

state: 

'success'

,

message: 

'This one worked as well.'

}, {

state: 

'error'

,

message: 

'This one did not work.'

}];

length = messages.length;

// bad

function

inbox(messages) {

items = 

'<ul>'

;

for

(i = 0; i < length; i++) {

items += 

'<li>'

+ messages[i].message + 

'</li>'

;

}

return

items + 

'</ul>'

;

}

// good

function

inbox(messages) {

items = [];

for

(i = 0; i < length; i++) {

// use direct assignment in this case because we're micro-optimizing.

items[i] = '<li>

' + messages[i].message + '

</li>

';

}

return '

<ul>

' + items.join('

') + '

</ul>';

}

函數

  • 函數表達式

// 匿名函數表達式

var

anonymous = 

function

() {

return

true

;

};

// 命名函數表達式

var

named = 

function

named() {

return

true

;

};

// 立即調用的函數表達式(IIFE)

(

function

() {

console.log(

'Welcome to the Internet. Please follow me.'

);

}());

  • 永遠不要在一個非函數代碼塊(if、while 等)中聲明一個函數,把那個函數賦給一個變量。浏覽器允許你這麼做,但它們的解析表現不一緻。
  • 注: ECMA-262 把 

     定義為一組語句。函數聲明不是語句。閱讀對 ECMA-262 這個問題的說明。(http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf#page=97)

// bad

if

(currentUser) {

function

test() {

console.log(

'Nope.'

);

}

}

// good

var

test;

if

(currentUser) {

test = 

function

test() {

console.log(

'Yup.'

);

};

}

  • 永遠不要把參數命名為 

    arguments

    。這将取代函數作用域内的 

    arguments

     對象。

// bad

function

nope(name, options, arguments) {

// ...stuff...

}

// good

function

yup(name, options, args) {

// ...stuff...

}

屬性

  • 使用 

    .

     來通路對象的屬性。

var

luke = {

jedi: 

true

,

age: 28

};

// bad

var

isJedi = luke[

'jedi'

];

// good

var

isJedi = luke.jedi;

  • 當通過變量通路屬性時使用中括号 

    []

var

luke = {

jedi: 

true

,

age: 28

};

function

getProp(prop) {

return

luke[prop];

}

var

isJedi = getProp(

'jedi'

);

變量

  • 總是使用 

    var

     來聲明變量。不這麼做将導緻産生全局變量。我們要避免污染全局命名空間。

// bad

superPower = 

new

SuperPower();

// good

var

superPower = 

new

SuperPower();

  • 使用 

    var

     聲明每一個變量。

    這樣做的好處是增加新變量将變的更加容易,而且你永遠不用再擔心調換錯 

    ;

     跟 

    ,

// bad

var

items = getItems(),

goSportsTeam = 

true

,

dragonball = 

'z'

;

// bad

// (跟上面的代碼比較一下,看看哪裡錯了)

var

items = getItems(),

goSportsTeam = 

true

;

dragonball = 

'z'

;

// good

var

items = getItems();

var

goSportsTeam = 

true

;

var

dragonball = 

'z'

;

  • 最後再聲明未指派的變量。當你需要引用前面的變量指派時這将變的很有用。

// bad

var

i, len, dragonball,

items = getItems(),

goSportsTeam = 

true

;

// bad

var

i;

var

items = getItems();

var

dragonball;

var

goSportsTeam = 

true

;

var

len;

// good

var

items = getItems();

var

goSportsTeam = 

true

;

var

dragonball;

var

length;

var

i;

  • 在作用域頂部聲明變量。這将幫你避免變量聲明提升相關的問題。

// bad

function

() {

test();

console.log(

'doing stuff..'

);

//..other stuff..

var

name = getName();

if

(name === 

'test'

) {

return

false

;

}

return

name;

}

// good

function

() {

var

name = getName();

test();

console.log(

'doing stuff..'

);

//..other stuff..

if

(name === 

'test'

) {

return

false

;

}

return

name;

}

// bad - 不必要的函數調用

function

() {

var

name = getName();

if

(!arguments.length) {

return

false

;

}

this

.setFirstName(name);

return

true

;

}

// good

function

() {

var

name;

if

(!arguments.length) {

return

false

;

}

name = getName();

this

.setFirstName(name);

return

true

;

}

提升

  • 變量聲明會提升至作用域頂部,但指派不會。

// 我們知道這樣不能正常工作(假設這裡沒有名為 notDefined 的全局變量)

function

example() {

console.log(notDefined); 

// => throws a ReferenceError

}

// 但由于變量聲明提升的原因,在一個變量引用後再建立它的變量聲明将可以正常工作。

// 注:變量指派為 `true` 不會提升。

function

example() {

console.log(declaredButNotAssigned); 

// => undefined

var

declaredButNotAssigned = 

true

;

}

// 解釋器會把變量聲明提升到作用域頂部,意味着我們的例子将被重寫成:

function

example() {

var

declaredButNotAssigned;

console.log(declaredButNotAssigned); 

// => undefined

declaredButNotAssigned = 

true

;

}

  • 匿名函數表達式會提升它們的變量名,但不會提升函數的指派。

function

example() {

console.log(anonymous); 

// => undefined

anonymous(); 

// => TypeError anonymous is not a function

var

anonymous = 

function

() {

console.log(

'anonymous function expression'

);

};

}

  • 命名函數表達式會提升變量名,但不會提升函數名或函數體。

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'

);

};

}

// 當函數名跟變量名一樣時,表現也是如此。

function

example() {

console.log(named); 

// => undefined

named(); 

// => TypeError named is not a function

var

named = 

function

named() {

console.log(

'named'

);

}

}

  • 函數聲明提升它們的名字和函數體。

function

example() {

superPower(); 

// => Flying

function

superPower() {

console.log(

'Flying'

);

}

}

  • 了解更多資訊在 JavaScript Scoping & Hoisting by Ben Cherry.(http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting)

比較運算符 & 等号

  • 優先使用 

    ===

     和 

    !==

     而不是 

    ==

     和 

    !=

    .
  • 條件表達式例如 

    if

     語句通過抽象方法 

    ToBoolean

     強制計算它們的表達式并且總是遵守下面的規則:
    • 對象 被計算為 true
    • Undefined 被計算為 false
    • Null 被計算為 false
    • 布爾值 被計算為 布爾的值
    • 數字 如果是 +0、-0 或 NaN 被計算為 false,否則為 true
    • 字元串 如果是空字元串 

      ''

       被計算為 false,否則為 true

if

([0]) {

// true

// 一個數組就是一個對象,對象被計算為 true

}

  • 使用快捷方式。

// bad

if

(name !== 

''

) {

// ...stuff...

}

// good

if

(name) {

// ...stuff...

}

// bad

if

(collection.length > 0) {

// ...stuff...

}

// good

if

(collection.length) {

// ...stuff...

}

  • 了解更多資訊在 Truth Equality and JavaScript by Angus Croll.(http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108)

  • 使用大括号包裹所有的多行代碼塊。

// bad

if

(test)

return

false

;

// good

if

(test) 

return

false

;

// good

if

(test) {

return

false

;

}

// bad

function

() { 

return

false

; }

// good

function

() {

return

false

;

}

  • 如果通過 

    if

     和 

    else

     使用多行代碼塊,把 

    else

     放在 

    if

     代碼塊關閉括号的同一行。

// bad

if

(test) {

thing1();

thing2();

}

else

{

thing3();

}

// good

if

(test) {

thing1();

thing2();

else

{

thing3();

}

注釋

  • 使用   作為多行注釋。包含描述、指定所有參數和傳回值的類型和值。

// bad

// make() returns a new element

// based on the passed in tag name

//

// @param {String} tag

// @return {Element} element

function

make(tag) {

// ...stuff...

return

element;

}

// good

function

make(tag) {

// ...stuff...

return

element;

}

  • 使用 

    //

     作為單行注釋。在評論對象上面另起一行使用單行注釋。在注釋前插入空行。

// bad

var

active = 

true

;  

// is current tab

// good

// is current tab

var

active = 

true

;

// bad

function

getType() {

console.log(

'fetching type...'

);

// set the default type to 'no type'

var

type = 

this

.type || 

'no type'

;

return

type;

}

// good

function

getType() {

console.log(

'fetching type...'

);

// set the default type to 'no type'

var

type = 

this

.type || 

'no type'

;

return

type;

}

  • 給注釋增加 

    FIXME

     或 

    TODO

     的字首可以幫助其他開發者快速了解這是一個需要複查的問題,或是給需要實作的功能提供一個解決方式。這将有别于常見的注釋,因為它們是可操作的。使用 

    FIXME -- need to figure this out

     或者 

    TODO -- need to implement

  • 使用 

    // FIXME:

     标注問題。

function

Calculator() {

// FIXME: shouldn't use a global here

total = 0;

return

this

;

}

  • 使用 

    // TODO:

     标注問題的解決方式。

function

Calculator() {

// TODO: total should be configurable by an options param

this

.total = 0;

return

this

;

}

空白

  • 使用 2 個空格作為縮進(如果習慣了用Tab 可以在編輯器中把Tab設定為2個空格。

// bad

function

() {

∙∙∙∙

var

name;

}

// bad

function

() {

var

name;

}

// good

function

() {

∙∙

var

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'

});

  • 在控制語句(

    if

    while

     等)的小括号前放一個空格。在函數調用及聲明中,不在函數的參數清單前加空格。

// bad

if

(isJedi) {

fight ();

}

// good

if

(isJedi) {

fight();

}

// bad

function

fight () {

console.log (

'Swooosh!'

);

}

// good

function

fight() {

console.log(

'Swooosh!'

);

}

  • 使用空格把運算符隔開。

// bad

var

x=y+5;

// good

var

x = y + 5;

  • 在檔案末尾插入一個空行。

// bad

(

function

(global) {

// ...stuff...

})(

this

);

// bad

(

function

(global) {

// ...stuff...

})(

this

);↵

// good

(

function

(global) {

// ...stuff...

})(

this

);↵

  • 在使用長方法鍊時進行縮進。使用前面的點 

    .

     強調這是方法調用而不是新語句。

// 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

var

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

var

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);

  • 在塊末和新語句前插入空行。

// bad

if

(foo) {

return

bar;

}

return

baz;

// good

if

(foo) {

return

bar;

}

return

baz;

// bad

var

obj = {

foo: 

function

() {

},

bar: 

function

() {

}

};

return

obj;

// good

var

obj = {

foo: 

function

() {

},

bar: 

function

() {

}

};

return

obj;

逗号

  • 行首逗号: 不需要。

// bad

var

story = [

once

, upon

, aTime

];

// good

var

story = [

once,

upon,

aTime

];

// bad

var

hero = {

firstName: 

'Bob'

, lastName: 

'Parr'

, heroName: 

'Mr. Incredible'

, superPower: 

'strength'

};

// good

var

hero = {

firstName: 

'Bob'

,

lastName: 

'Parr'

,

heroName: 

'Mr. Incredible'

,

superPower: 

'strength'

};

  • 額外的行末逗号:不需要。這樣做會在 IE6/7 和 IE9 怪異模式下引起問題。同樣,多餘的逗号在某些 ES3 的實作裡會增加數組的長度。在 ES5 中已經澄清了 (source):

> Edition 5 clarifies the fact that a trailing comma at the end of an ArrayInitialiser does not add to the length of the array. This is not a semantic change from Edition 3 but some implementations may have previously misinterpreted this.

// bad

var

hero = {

firstName: 

'Kevin'

,

lastName: 

'Flynn'

,

};

var

heroes = [

'Batman'

,

'Superman'

,

];

// good

var

hero = {

firstName: 

'Kevin'

,

lastName: 

'Flynn'

};

var

heroes = [

'Batman'

,

'Superman'

];

分号

  • 使用分号。

// bad

(

function

() {

var

name = 

'Skywalker'

return

name

})()

// good

(

function

() {

var

name = 

'Skywalker'

;

return

name;

})();

// good (防止函數在兩個 IIFE 合并時被當成一個參數

;(

function

() {

var

name = 

'Skywalker'

;

return

name;

})();

[了解更多](http://stackoverflow.com/a/7365214/1712802).
           

類型轉換

  • 在語句開始時執行類型轉換。
  • 字元串:

//  => this.reviewScore = 9;

// bad

var

totalScore = 

this

.reviewScore + 

''

;

// good

var

totalScore = 

''

this

.reviewScore;

// bad

var

totalScore = 

''

this

.reviewScore + 

' total score'

;

// good

var

totalScore = 

this

.reviewScore + 

' total score'

;

  • 使用 

    parseInt

     轉換數字時總是帶上類型轉換的基數。

var

inputValue = 

'4'

;

// bad

var

val = 

new

Number(inputValue);

// bad

var

val = +inputValue;

// bad

var

val = inputValue >> 0;

// bad

var

val = parseInt(inputValue);

// good

var

val = Number(inputValue);

// good

var

val = parseInt(inputValue, 10);

  • 如果因為某些原因 

    parseInt

     成為你所做的事的瓶頸而需要使用位操作解決性能問題(http://jsperf.com/coercion-vs-casting/3)時,留個注釋說清楚原因和你的目的。

// good

var

val = inputValue >> 0;

  • 注: 小心使用位操作運算符。數字會被當成 64 位值(http://es5.github.io/#x4.3.19),但是位操作運算符總是傳回 32 位的整數(source(http://es5.github.io/#x11.7))。位操作處理大于 32 位的整數值時還會導緻意料之外的行為。最大的 32 位整數是 2,147,483,647:

2147483647 >> 0 

//=> 2147483647

2147483648 >> 0 

//=> -2147483648

2147483649 >> 0 

//=> -2147483647

  • 布爾:

var

age = 0;

// bad

var

hasAge = 

new

Boolean(age);

// good

var

hasAge = Boolean(age);

// good

var

hasAge = !!age;

存取器

  • 屬性的存取函數不是必須的。
  • 如果你需要存取函數時使用 

    getVal()

     和 

    setVal('hello')

// bad

dragon.age();

// good

dragon.getAge();

// bad

dragon.age(25);

// good

dragon.setAge(25);

  • 如果屬性是布爾值,使用 

    isVal()

     或 

    hasVal()

// bad

if

(!dragon.age()) {

return

false

;

}

// good

if

(!dragon.hasAge()) {

return

false

;

}

  • 建立 get() 和 set() 函數是可以的,但要保持一緻。

function

Jedi(options) {

options || (options = {});

var

lightsaber = options.lightsaber || 

'blue'

;

this

.set(

'lightsaber'

, lightsaber);

}

Jedi.prototype.set = 

function

set(key, val) {

this

[key] = val;

};

Jedi.prototype.get = 

function

get(key) {

return

this

[key];

};

構造函數

  • 給對象原型配置設定方法,而不是使用一個新對象覆寫原型。覆寫原型将導緻繼承出現問題:重設原型将覆寫原有原型!

function

Jedi() {

console.log(

'new jedi'

);

}

// bad

Jedi.prototype = {

fight: 

function

fight() {

console.log(

'fighting'

);

},

block: 

function

block() {

console.log(

'blocking'

);

}

};

// good

Jedi.prototype.fight = 

function

fight() {

console.log(

'fighting'

);

};

Jedi.prototype.block = 

function

block() {

console.log(

'blocking'

);

};

  • 方法可以傳回 

    this

     來實作方法鍊式使用。

// bad

Jedi.prototype.jump = 

function

jump() {

this

.jumping = 

true

;

return

true

;

};

Jedi.prototype.setHeight = 

function

setHeight(height) {

this

.height = height;

};

var

luke = 

new

Jedi();

luke.jump(); 

// => true

luke.setHeight(20); 

// => undefined

// good

Jedi.prototype.jump = 

function

jump() {

this

.jumping = 

true

;

return

this

;

};

Jedi.prototype.setHeight = 

function

setHeight(height) {

this

.height = height;

return

this

;

};

var

luke = 

new

Jedi();

luke.jump()

.setHeight(20);

  • 寫一個自定義的 

    toString()

     方法是可以的,但是確定它可以正常工作且不會産生副作用。

function

Jedi(options) {

options || (options = {});

this

.name = options.name || 

'no name'

;

}

Jedi.prototype.getName = 

function

getName() {

return

this

.name;

};

Jedi.prototype.toString = 

function

toString() {

return

'Jedi - '

this

.getName();

};

事件

  • 當給事件附加資料時(無論是 DOM 事件還是私有事件),傳入一個哈希而不是原始值。這樣可以讓後面的貢獻者增加更多資料到事件資料而無需找出并更新事件的每一個處理器。例如,不好的寫法:

// bad

$(

this

).trigger(

'listingUpdated'

, listing.id);

...

$(

this

).on(

'listingUpdated'

function

(e, listingId) {

// do something with listingId

});

// good

$(

this

).trigger(

'listingUpdated'

, { listingId : listing.id });

...

$(

this

).on(

'listingUpdated'

function

(e, data) {

// do something with data.listingId

});

子產品

  • 子產品應該以 

    !

     開始。這樣確定了當一個不好的子產品忘記包含最後的分号時,在合并代碼到生産環境後不會産生錯誤。詳細說明(https://github.com/airbnb/javascript/issues/44#issuecomment-13063933)
  • 檔案應該以駝峰式命名,并放在同名的檔案夾裡,且與導出的名字一緻。
  • 增加一個名為 

    noConflict()

     的方法來設定導出的子產品為前一個版本并傳回它。
  • 永遠在子產品頂部聲明 

    'use strict';

// fancyInput/fancyInput.js

!

function

(global) {

'use strict'

;

var

previousFancyInput = global.FancyInput;

function

FancyInput(options) {

this

.options = options || {};

}

FancyInput.noConflict = 

function

noConflict() {

global.FancyInput = previousFancyInput;

return

FancyInput;

};

global.FancyInput = FancyInput;

}(

this

);

⬆ 回到頂部

jQuery

  • 使用 

    $

     作為存儲 jQuery 對象的變量名字首。

// bad

var

sidebar = $(

'.sidebar'

);

// good

var

$sidebar = $(

'.sidebar'

);

  • 緩存 jQuery 查詢。

// bad

function

setSidebar() {

$(

'.sidebar'

).hide();

// ...stuff...

$(

'.sidebar'

).css({

'background-color'

'pink'

});

}

// good

function

setSidebar() {

var

$sidebar = $(

'.sidebar'

);

$sidebar.hide();

// ...stuff...

$sidebar.css({

'background-color'

'pink'

});

}

  • 對 DOM 查詢使用層疊 

    $('.sidebar ul')

     或 父元素 > 子元素 

    $('.sidebar > ul')

    。 jsPerf(http://jsperf.com/jquery-find-vs-context-sel/16)
  • 對有作用域的 jQuery 對象查詢使用 

    find

// bad

$(

'ul'

'.sidebar'

).hide();

// bad

$(

'.sidebar'

).find(

'ul'

).hide();

// good

$(

'.sidebar ul'

).hide();

// good

$(

'.sidebar > ul'

).hide();

// good

$sidebar.find(

'ul'

).hide();

ECMAScript 5 相容性

  • 參考 Kangax 的 ES5 相容表.(http://kangax.github.com/es5-compat-table/)

⬆ 回到頂部

測試

  • Yup.

function

() {

return

true

;

}

⬆ 回到頂部

性能

  • On Layout & Web Performance(http://kellegous.com/j/2013/01/26/layout-performance/)
  • String vs Array Concat(http://jsperf.com/string-vs-array-concat/2)
  • Try/Catch Cost In a Loop(http://jsperf.com/try-catch-in-loop-cost)
  • Bang Function(http://jsperf.com/bang-function)
  • jQuery Find vs Context, Selector(http://jsperf.com/jquery-find-vs-context-sel/13)
  • innerHTML vs textContent for script text(http://jsperf.com/innerhtml-vs-textcontent-for-script-text)
  • Long String Concatenation(http://jsperf.com/ya-string-concat)
  • Loading…

⬆ 回到頂部

推薦閱讀

  • Annotated ECMAScript 5.1(http://es5.github.com/)

工具

  • Code Style Linters
    • JSHint - Airbnb Style .jshintrc(https://github.com/airbnb/javascript/blob/master/linters/.jshintrc)
    • JSCS - Airbnb Style Preset (https://github.com/jscs-dev/node-jscs/blob/master/presets/airbnb.json)

其它風格指南

  • Google JavaScript Style Guide (http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml)
  • jQuery Core Style Guidelines (http://docs.jquery.com/JQuery_Core_Style_Guidelines)
  • Principles of Writing Consistent, Idiomatic JavaScript (https://github.com/rwldrn/idiomatic.js/)
  • JavaScript Standard Style (https://github.com/feross/standard)

其它風格

  • Naming this in nested functions - Christian Johansen  (https://gist.github.com/4135065)
  • Conditional Callbacks - Ross Allen (https://github.com/airbnb/javascript/issues/52)
  • Popular JavaScript Coding Conventions on Github - JeongHoon Byun (http://sideeffect.kr/popularconvention/#javascript)
  • Multiple var statements in JavaScript, not superfluous - Ben Alman (http://benalman.com/news/2012/05/multiple-var-statements-javascript/)

進一步閱讀

  • Understanding JavaScript Closures - Angus Croll  (http://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/)
  • Basic JavaScript for the impatient programmer - Dr. Axel Rauschmayer (http://www.2ality.com/2013/06/basic-javascript.html)
  • You Might Not Need jQuery - Zack Bloom & Adam Schwartz (http://youmightnotneedjquery.com/)
  • ES6 Features - Luke Hoban  (https://github.com/lukehoban/es6features)
  • Frontend Guidelines - Benjamin De Cock  (https://github.com/bendc/frontend-guidelines)

繼續閱讀