Skip to content

yangboOne/javascript-code-style

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 

Repository files navigation

Airbnb 的javascript规范指南

常用的一些javascript规范

  1. 数据类型
  2. 对象
  3. 数组
  4. string类型
  5. 函数
  6. 属性
  7. 变量
  8. 声明提前
  9. 条件表达式与等式
  10. 注释
  11. 空格
  12. 逗号
  13. Semicolons
  14. Type Casting & Coercion
  15. Naming Conventions
  16. Accessors
  17. Constructors
  18. Events
  19. Modules
  20. jQuery
  21. ES5 Compatibility
  22. Testing
  23. Performance
  24. Resources
  25. In the Wild
  26. Translation
  27. The JavaScript Style Guide Guide
  28. Contributors
  29. License
  • 原始类型(Primitives):当你给一个原始类型赋值时,返回的是这个值的本身。

    • string
    • number
    • boolean
    • null
    • undefined
    var foo = 1,
        bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); // => 1, 9
  • 对象类型:当你给一个对象类型赋值时,返回的是这个值的引用。

    • object
    • array
    • function
    var foo = [1, 2],
        bar = foo;
    
    bar[0] = 9;
    
    console.log(foo[0], bar[0]); // => 9, 9
  • 新建一个对象的语法

    //不推荐
    var item = new Object();
    
    //推荐
    var item = {};
  • 不要使用保留字作为键值,否则在IE8下面会出现问题(详情)。

    //不推荐
    var superman = {
      default: { clark: 'kent'},
      private: true
    };
    
    //推荐
    var superman ={
      defaults: { clark: 'kent'},
      hidden: true
    };
  • 使用可读性强的同义词代替保留字

    //不推荐
    var superman = {
      class: 'alien'
    };
    
    //不推荐
    var superman = {
      klass: 'alien'
    };
    
    //推荐
    var superman = {
      type: 'alien'
    };
  • 新建一个数组的语法

    //不推荐
    var items = new Array();
    
    //推荐
    var items = [];
  • 如果你不知道数组的长度可以使用push将元素加入。

    var someStack = [];
    
    //不推荐
    someStack[someStack.length] = 'something';
    
    //推荐
    someStack.push('something');
  • 当你需要复制一个数组的时候使用slice。jsPerf

    var len = items.length,
      itemsCopy = [],
      i;
    
    //不推荐
    for (i = 0; i < len; i++){
      itemsCopy[i] = items[i];
    }
    
    //推荐
    itemsCopy = items.slice();
  • 用slice转换伪数组对象到数组

    function trigger() {
      var args = Array.prototype.slice.call(arguments);
      ...
    }
  • 使用单引号''

    //不推荐
    var name = "Bob Parr";
    
    //推荐
    var name = 'Bob Parr';
    
    //不推荐
    var fullName - "Bob " + this.lastName;
    
    //推荐
    var fullName = 'Bob ' + this.lastName;
  • 当字符串长度超过80个时,应该通过字符串连接多行显示。

  • 注意:过度使用字符串连接将会影响性能。jsPerf&Discussion

    //不推荐
    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.';
    
    //不推荐
    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.';
    
    //推荐
    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.';
  • 当程序建立一个字符串时, 使用join代替字符串连接。特别是在IE下:jsPerf

    var items,
        messages,
        length, 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;
    
    // 不推荐
    function inbox(messages) {
      items = '<ul>';
    
      for (i = 0; i < length; i++) {
        items += '<li>' + messages[i].message + '</li>';
      }
    
      return items + '</ul>';
    }
    
    // 推荐
    function inbox(messages) {
      items = [];
    
      for (i = 0; i < length; i++) {
        items[i] = messages[i].message;
      }
    
      return '<ul><li>' + items.join('</li><li>') + '</li></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的文档

    //不推荐
    if (currentUser){
      function test() {
        console.log('Nope.');
      }
    }
    
    //推荐
    if (currentUser){
      var test = function test() {
        console.log('Yup.');
      }
    }
  • arguments 不能作为一个参数的名字, 因为这会覆盖每一个函数内的arguments对象。

    //不推荐
    function nope(name, options, arguments) {
      // ...stuff...
    }
    
    //推荐
    function yup(name, options, args) {
      // ...stuff...
    }
  • 访问一个属性时,使用点的形式取值。

    var luke = {
      jedi: true,
      age: 28
    };
    
    // 不推荐
    var isJedi = luke['jedi'];
    
    // 推荐
    var isJedi = luke.jedi;
  • 需要一个变量访问一个属性时,使用“[]”来取值。

    var luke = {
      jedi: true,
      age: 28
    };
    
    function getProp(prop) {
      return luke[prop];
    }
    
    var isJedi = getProp('jedi');
  • 总是使用 var 来定义变量。如果不这么做将定义一个全局变量出来。我们希望避免全局命名空间的污染。

    // 不推荐
    superPower = new SuperPower();
    
    // 推荐
    var superPower = new SuperPower();
  • 使用一个var 声明多个变量,并且每声明一个变量就换一行。

    // 不推荐
    var items = getItems();
    var goSportsTeam = true;
    var dragonball = 'z';
    
    // 推荐
    var items = getItems(),
        goSportsTeam = true,
        dragonball = 'z';
  • 声明多个变量时,把不赋值的变量放在后面。这样做是有好处的,如果日后你想给未赋值变量赋值的时候,可能要引用到上面已经赋值的变量。

    // 不推荐
    var i, len, dragonball,
        items = getItems(),
        goSportsTeam = true;
    
    // 不推荐
    var i, items = getItems(),
        dragonball,
        goSportsTeam = true,
        len;
    
    // 推荐
    var items = getItems(),
        goSportsTeam = true,
        dragonball,
        length,
        i;
  • 在一个作用域的顶部给一个变量赋值。这样有助于避开,变量声明和声明提前的分配问题。

    // 不推荐
    function() {
      test();
      console.log('doing stuff..');
    
      //..other stuff..
    
      var name = getName();
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // 推荐
    function() {
      var name = getName();
    
      test();
      console.log('doing stuff..');
    
      //..other stuff..
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // 不推荐
    function() {
      var name = getName();
    
      if (!arguments.length) {
        return false;
      }
    
      return true;
    }
    
    // 推荐
    function() {
      if (!arguments.length) {
        return false;
      }
    
      var name = getName();
    
      return true;
    }
  • 不管你在何处给一个变量声明或赋值,javascript解析器都会事先在作用域的顶端做声明提前(Hoisting)。

    // 我们知道下面将不能正常运行(假设没有全局变量)
    function example() {
      console.log(notDefined); // => 抛出一个引用错误
    }
    
    // 在引用这个变量之后,给这个变量赋值将不会抛异常,这是因为javascript解析器有声明提前。
    // 注意:赋的“true”值,不会被提前。
    function example() {
      console.log(declaredButNotAssigned); // => undefined
      var declaredButNotAssigned = true;
    }
    
    // javascript解析器,会在作用域的顶部提前声明变量。
    // 用代码描述出来,其实就等同于下面这种情况。
    function example() {
      var declaredButNotAssigned;
      console.log(declaredButNotAssigned); // => undefined
      declaredButNotAssigned = true;
    }
  • 匿名函数表达式将该变量名做了提前声明,没有给该变量赋值函数。

    function example() {
      console.log(anonymous); // => undefined
    
      anonymous(); // => 抛出异常,anonymous 不是一个函数
    
      var anonymous = function() {
        console.log('anonymous function expression');
      };
    }
  • 和匿名一样,有名函数表达式将该变量名做了提前声明,没有给该变量赋值函数名和函数体。

    function example() {
      console.log(named); // => undefined
    
      named(); // => 抛出异常, named 不是一个函数
    
      superPower(); // => 抛出异常, superPower 没定义
    
      var named = function superPower() {
        console.log('Flying');
      };
    }
    
    // 把函数名改成和变量名一样,也得出同样的结果。
    function example() {
      console.log(named); // => undefined
    
      named(); // => 抛出异常, named 不是一个函数
    
      var named = function named() {
        console.log('named');
      };
    }
  • 函数声明会将函数名和函数体声明提前。

    function example() {
      superPower(); // => Flying
    
      function superPower() {
        console.log('Flying');
      }
    }
  • 更多信息请参照 Ben CherryJavaScript Scoping & Hoisting

  • 使用 ===!== 代替 ==!=

  • 条件表达式 会通过 ToBoolean 来进行强制转化,而且遵循以下的规则:

    • 对象被转化为true
    • Undefined被转化为false
    • Null被转化为false
    • 布尔值被转化为相应的布尔值
    • 数字当值为**+0**,-0NaN时转化为false,其他的转化为true
    • Strings类型如果为空时转化为false,否则转化为true
    if ([0]) {
        // true    
        // 因为数组是对象,对象会被转化为 true
    }
  • 使用快捷方式

    // 不推荐
    if (name !== '') {
      // ...stuff...
    }
    
    // 推荐
    if (name) {
      // ...stuff...
    }
    
    // 不推荐
    if (collection.length > 0) {
      // ...stuff...
    }
    
    // 推荐
    if (collection.length) {
      // ...stuff...
    }
  • 更多的信息 请看 Angus Croll 的 Truth Equality and JavaScript

  • 给多行的块,使用大括号

    // 不推荐
    if (test)
      return false;
    
    // 推荐
    if (test) return false;
    
    // 推荐
    if (test) {
      return false;
    }
    
    // 不推荐
    function() { return false; }
    
    // 推荐
    function() {
      return false;
    }
  • 使用 /**...*/ 进行多行注释。注释要包括描述、指定类型、参数值和返回值。

    // 不推荐
    
    // make() returns a new element
    // based on the passed in tag name
    //
    // @param <String> tag
    // @return <Element> element
    function make(tag) {
    
      // ...stuff...
    
      return element;
    }
    
    // 推荐
    /**
     * make() returns a new element
     * based on the passed in tag name
     *
     * @param <String> tag
     * @return <Element> element
     */
    function make(tag) {
    
      // ...stuff...
    
      return element;
    }
  • 使用 // 进行单行注释。注释单独占一行,并写在需要注释对象的上面。在注释的上面留一个空行。

    // 不推荐
    var active = true;  // is current tab
    
    // 推荐
    // is current tab
    var active = true;
    
    // 不推荐
    function getType() {
      console.log('fetching type...');
      // set the default type to 'no type'
      var type = this._type || 'no type';
    
      return type;
    }
    
    // 推荐
    function getType() {
      console.log('fetching type...');
    
      // set the default type to 'no type'
      var type = this._type || 'no type';
    
      return type;
    }
  • 给你的代码加前缀,比如FIXMETODO,这样有助于其他开发者可以迅速理解你指出的需要被处理的问题。 如果想更清晰一点你还可以在后面加上描述,比如: FIXME -- need to figure this outTODO -- 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;
    }
  • 将tab键设成2个空格

    // 不推荐
    function() {
    ∙∙∙∙var name;
    }
    
    // 不推荐
    function() {
    ∙var name;
    }
    
    // 推荐
    function() {
    ∙∙var name;
    } 
  • 逗号/冒号/小括号后面留一个空格

    // 不推荐
    function test(){
      console.log('test');
    }
    
    // 推荐
    function test() {
      console.log('test');
    }
    
    // 不推荐
    dog.set('attr',{
      age: '1 year',
      breed: 'Bernese Mountain Dog'
    });
    
    // 推荐
    dog.set('attr', {
      age: '1 year',
      breed: 'Bernese Mountain Dog'
    });
  • 在文件的最后留一个空行

    // 不推荐
    (function(global) {
      // ...stuff...
    })(this);
    // 推荐
    (function(global) {
      // ...stuff...
    })(this);
  • 逗号不要前置

    // 不推荐
    var once
      , upon
      , aTime;
    
    // 推荐
    var once,
        upon,
        aTime;
    
    // 不推荐
    var hero = {
        firstName: 'Bob'
      , lastName: 'Parr'
      , heroName: 'Mr. Incredible'
      , superPower: 'strength'
    };
    
    // 推荐
    var hero = {
      firstName: 'Bob',
      lastName: 'Parr',
      heroName: 'Mr. Incredible',
      superPower: 'strength'
    };
  • 最后一个元素不可以加逗号。这在IE6和IE7还有IE9的怪异模式下出错。

Releases

No releases published

Packages

No packages published