JavaScript 風格指南/編碼規範(Airbnb公司版)二

  • 提升

  • 變量聲明在範圍內提升,但賦值並沒有提升
// 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() {
  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');
  };
}
 
// 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');
  }
}

  • 函數聲明能提升他們的函數名和函數體
function example() {
  superPower(); // => Flying
 
  function superPower() {
    console.log('Flying');
  }
}

  • 條件表達式和相等

  • 條件表達式強制使用 ToBoolean方法進行解析,並遵從以下簡單的規則Object :返回 true
  • Undefined: 返回 false
  • Null: 返回 false
  • Booleans :返回 boolean的值
  • Numbers :如果是+0, -0, or NaN返回 false, 其他則 true
  • Strings :空字符串''返回 false 其他返回true
if ([0]) {
  // true
  // An array is an object, objects evaluate to true
}

  • 使用簡易方式
// bad
if (name !== '') {
  // ...stuff...
}
 
// good
if (name) {
  // ...stuff...
}
 
// bad
if (collection.length > 0) {
  // ...stuff...
}
 
// good
if (collection.length) {
  // ...stuff...
}

  • 在多行塊中使用大括號
// bad
if (test)
  return false;
 
// good
if (test) return false;
 
// good
if (test) {
  return false;
}
 
// bad
function() { return false; }
 
// good
function() {
  return false;
}

註釋

  • 多行註釋使用 /** ... */ ,包括描述,指定類型、所有參數的值和返回值
// 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
/**
 * make() returns a new element
 * based on the passed in tag name
 *
 * @param <String> tag
 * @return <Element> element
 */
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——是需要解決的而TODO——是需要完善的
  • 使用// 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;
}

  • 空格

  • 使用tabs設置兩個空格
// 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'
});

  • 操作符前後空一格
// 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();
 
// good
$('#items')
  .find('.selected')
    .highlight()
    .end()
  .find('.open')
    .updateCount();
 
// bad
var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('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')
    .class('led', true)
    .attr('width',  (radius + margin) * 2)
  .append('svg:g')
    .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
    .call(tron.led);

  • 逗號

  • 不要在句首使用逗號
// bad
var once
  , upon
  , aTime;
 
// good
var 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):
// 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 (guards against the function becoming an argument when two files with IIFEs are concatenated)
;(function() {
  var name = 'Skywalker';
  return name;
})();

  • 轉型&強制

  • 在語句的開頭執行強制轉型。
  • Strings:
//  => 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';

  • 使用parseIntNumbers型進行強制轉型。
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是你的瓶頸,出於性能考慮你需要使用位移,那麼留下你的註釋來解釋原因。
// good
/**
 * parseInt was the reason my code was slow.
 * Bitshifting the String to coerce it to a
 * Number made it a lot faster.
 */
var val = inputValue >> 0;

  • 注意:小心位移操作符,Numbers代表着64位的值,而位移操作符只能返回32位的整型,位移對於大於32位的整型的值會有不好的影響,32位最大的有符號整型是2,147,483,647。
  • (有關討論:Discussion
2147483647 >> 0 //=> 2147483647
2147483648 >> 0 //=> -2147483648
2147483649 >> 0 //=> -2147483647

  • Booleans:
var age = 0;
 
// bad
var hasAge = new Boolean(age);
 
// good
var hasAge = Boolean(age);
 
// good
var hasAge = !!age;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章