【转】JavaScript 风格指南/编码规范(Airbnb公司版)

原文转自:http://blog.jobbole.com/79484/

Airbnb 是一家位于美国旧金山的公司,本文是其内部的 JavaScript 风格指南/编码规范,在 Github 上有 11,000+ Star,2100+ fork,前端开发者可参考。

  • 基本类型:当你访问基本类型时,你是直接对它的值进行操作。
    • string
    • number
    • boolean
    • null
    • undefined

      1

      2

      3

      4

      5

      6

      var foo = 1,

      bar = foo;

      bar = 9;

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

  • object
  • array
  • function

1

2

3

4

5

6

var foo = [1, 2],

bar = foo;

bar[0] = 9;

console.log(foo[0], bar[0]); // => 9, 9

对象

  • 使用字面量语法来创建对象

  • 1

    2

    3

    4

    5

    // bad

    var item = new Object();

    // good

    var item = {};

  • 不要使用保留字作为“键值”,因为在IE8不能运行。More info

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    // bad

    var superman = {

      default: { clark: ‘kent‘ },

      private: true

    };

    // good

    var superman = {

      defaults: { clark: ‘kent‘ },

      hidden: true

    };

  • 使用容易理解的同义词来替代保留字

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    // bad

    var superman = {

      class: ‘alien‘

    };

    // bad

    var superman = {

      klass: ‘alien‘

    };

    // good

    var superman = {

      type: ‘alien‘

    };

  • 数组

  • 使用字面量语法来创建数组

  • 1

    2

    3

    4

    5

    // bad

    var items = new Array();

    // good

    var items = [];

  • 如果你不知道数组长度,数组添加成员使用push方法。

  • 1

    2

    3

    4

    5

    6

    7

    var someStack = [];

    // bad

    someStack[someStack.length] = ‘abracadabra‘;

    // good

    someStack.push(‘abracadabra‘);

  • 当你需要复制一个数组时,使用数组的slice方法。jsPerf

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    var len = items.length,

        itemsCopy = [],

        i;

    // bad

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

      itemsCopy[i] = items[i];

    }

    // good

    itemsCopy = items.slice();

  • 当你需要把“类似数组对象”转为数组时,使用数组的slice方法。

  • 1

    2

    3

    4

    function trigger() {

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

      ...

    }

  • 字符串

  • 字符串使用单引号‘’

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    // bad

    var name = "Bob Parr";

    // good

    var name = ‘Bob Parr‘;

    // bad

    var fullName = "Bob " + this.lastName;

    // good

    var fullName = ‘Bob ‘ + this.lastName;

  • 大于80个元素的字符串需要通过分隔符进行多行操作。
  • 注意:如果在长字符串中过度使用分隔符会影响性能。. jsPerf & Discussion

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    // 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.‘;

  • 通过编程的方式创建字符串,应该使用数组的join方法,而不是字符串链接方法。特别是对于IE而言。 jsPerf.

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    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;

    // 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++) {

        items[i] = messages[i].message;

      }

      return ‘<ul><li>‘ + items.join(‘</li><li>‘) + ‘</li></ul>‘;

  • 函数

  • 函数表达式

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    // anonymous function expression

    var anonymous = function() {

      return true;

    };

    // named function expression

    var named = function named() {

      return true;

    };

    // immediately-invoked function expression (IIFE)

    (function() {

      console.log(‘Welcome to the Internet. Please follow me.‘);

    })();

  • 不要直接在非函数块(if,while等)里声明一个函数,最好将函数赋值给一个变量。虽然浏览器允许你在非函数块中声明函数,但是由于不同的浏览器对Javascript的解析方式不同,这样做就很可能造成麻烦。
  • 注意:ECMA-262 将块定义为一组语句,而函数声明不是语句。Read ECMA-262′s note on this issue

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    // bad

    if (currentUser) {

      function test() {

        console.log(‘Nope.‘);

      }

    }

    // good

    var test;

    if (currentUser) {

      test = function test() {

        console.log(‘Yup.‘);

      };

    }

  • 不要将参数命名为arguments,它将在每个函数的作用范围内优先于arguments对象。

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    // bad

    function nope(name, options, arguments) {

      // ...stuff...

    }

    // good

    function yup(name, options, args) {

      // ...stuff...

    }

  • 属性

  • 使用点符号 . 来访问属性

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    var luke = {

      jedi: true,

      age: 28

    };

    // bad

    var isJedi = luke[‘jedi‘];

    // good

    var isJedi = luke.jedi;

  • 当你在变量中访问属性时,使用[ ]符号

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    var luke = {

      jedi: true,

      age: 28

    };

    function getProp(prop) {

      return luke[prop];

    }

    var isJedi = getProp(‘jedi‘);

  • 变量

  • 使用var来声明变量,否则将声明全局变量,我们需要尽量避免污染全局命名空间,Captain Planet这样警告过我们。

  • 1

    2

    3

    4

    5

    // bad

    superPower = new SuperPower();

    // good

    var superPower = new SuperPower();

  • 多个变量时只使用一个var声明,每个变量占一新行。

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    // bad

    var items = getItems();

    var goSportsTeam = true;

    var dragonball = ‘z‘;

    // good

    var items = getItems(),

        goSportsTeam = true,

        dragonball = ‘z‘;

  • 最后再声明未赋值的变量,这对你之后需要依赖之前变量的变量赋值会有帮助。

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    // bad

    var i, len, dragonball,

        items = getItems(),

        goSportsTeam = true;

    // bad

    var i, items = getItems(),

        dragonball,

        goSportsTeam = true,

        len;

    // good

    var items = getItems(),

        goSportsTeam = true,

        dragonball,

        length,

        i;

    ·

  • 在范围内将变量赋值置顶,这有助于避免变量声明和赋值提升相关的问题

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

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

      }

      return true;

    }

    // good

    function() {

      if (!arguments.length) {

        return false;

      }

      var name = getName();

      return true;

    }

  • 提升

  • 变量声明在范围内提升,但赋值并没有提升

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

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

    }

  • 匿名函数表达式提升变量名,但函数赋值并没有提升,

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    · function example() {

      console.log(anonymous); // => undefined

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

      var anonymous = function() {

        console.log(‘anonymous function expression‘);

      };

    }

  • 命名函数表达式提升变量名,但函数名字和函数体并没有提升。

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

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

      }

    }

  • 函数声明能提升他们的函数名和函数体

  • 1

    2

    3

    4

    5

    6

    7

    function example() {

      superPower(); // => Flying

      function superPower() {

        console.log(‘Flying‘);

      }

    }

  • 更多的信息在JavaScript Scoping & Hoisting by Ben Cherry
  • 条件表达式和相等

  • 条件表达式强制使用 ToBoolean方法进行解析,并遵从以下简单的规则Object :返回 true
  • Undefined 返回 false
  • Null 返回 false
  • Booleans :返回 boolean的值
  • Numbers :如果是+0, -0, or NaN返回 false, 其他则 true
  • Strings :空字符串‘‘返回 false 其他返回true

  • 1

    2

    3

    4

    if ([0]) {

      // true

      // An array is an object, objects evaluate to true

    }

  • 使用简易方式

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

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

  • 在多行块中使用大括号

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// bad

if (test)

  return false;

// good

if (test) return false;

// good

if (test) {

  return false;

}

// bad

function() { return false; }

// good

function() {

  return false;

}

注释

  • 多行注释使用 /** ... */ ,包括描述,指定类型、所有参数的值和返回值

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

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

    }

  • 单行注释使用 //, 在注释的内容前另起一行进行单行注释,并在注释前留一空行。

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    // 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: 来标记问题

  • 1

    2

    3

    4

    5

    6

    7

    function Calculator() {

      // FIXME: shouldn‘t use a global here

      total = 0;

      return this;

    }

  • 使用 // TODO:给待解决问题进行标注

  • 1

    2

    3

    4

    5

    6

    7

    function Calculator() {

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

      this.total = 0;

      return this;

    }

  • 空格

  • 使用tabs设置两个空格

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    // bad

    function() {

    ????var name;

    }

    // bad

    function() {

    ?var name;

    }

    // good

    function() {

    ??var name;

    }

  • 分支前面空一格

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

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

    });

  • 操作符前后空一格

  • 1

    2

    3

    4

    5

    // bad

    var x=y+5;

    // good

    var x = y + 5;

  • 文件末尾用换行符结束

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    // bad

    (function(global) {

      // ...stuff...

    })(this);

    // bad

    (function(global) {

      // ...stuff...

    })(this);

    // good

    (function(global) {

      // ...stuff...

    })(this)

  • 使用长方法链时使用缩进

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

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

  • 逗号

  • 不要在句首使用逗号

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

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

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    // bad

      var hero = {

        firstName: ‘Kevin‘,

        lastName: ‘Flynn‘,

      };

      var heroes = [

        ‘Batman‘,

        ‘Superman‘,

      ];

      // good

      var hero = {

        firstName: ‘Kevin‘,

        lastName: ‘Flynn‘

      };

      var heroes = [

        ‘Batman‘,

        ‘Superman‘

      ];

  • 分号


    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

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

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    //  => 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型进行强制转型。

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    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是你的瓶颈,出于性能考虑你需要使用位移,那么留下你的注释来解释原因。

  • 1

    2

    3

    4

    5

    6

    7

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

  • 1

    2

    3

    2147483647 >> 0 //=> 2147483647

    2147483648 >> 0 //=> -2147483648

    2147483649 >> 0 //=> -2147483647

  • Booleans:

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    var age = 0;

    // bad

    var hasAge = new Boolean(age);

    // good

    var hasAge = Boolean(age);

    // good

    var hasAge = !!age;

  • 命名规则

  • 不要使用一个字母命名,而应该用单词描述

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    // bad

    function q() {

      // ...stuff...

    }

    // good

    function query() {

      // ..stuff..

    }

  • 使用驼峰法来给对象、函数、实例命名。

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    // bad

    var OBJEcttsssss = {};

    var this_is_my_object = {};

    function c() {}

    var u = new user({

      name: ‘Bob Parr‘

    });

    // good

    var thisIsMyObject = {};

    function thisIsMyFunction() {}

    var user = new User({

      name: ‘Bob Parr‘

    });

  • 使用驼峰式大小写给构造函数和类命名。

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    // bad

    function user(options) {

      this.name = options.name;

    }

    var bad = new user({

      name: ‘nope‘

    });

    // good

    function User(options) {

      this.name = options.name;

    }

    var good = new User({

      name: ‘yup‘

    });

  • 使用下划线前缀_来命名私有属性。

  • 1

    2

    3

    4

    5

    6

    // bad

    this.__firstName__ = ‘Panda‘;

    this.firstName_ = ‘Panda‘;

    // good

    this._firstName = ‘Panda‘;

  • 储存this的引用使用_this

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    // bad

    function() {

      var self = this;

      return function() {

        console.log(self);

      };

    }

    // bad

    function() {

      var that = this;

      return function() {

        console.log(that);

      };

    }

    // good

    function() {

      var _this = this;

      return function() {

        console.log(_this);

      };

    }

  • 给你的函数命名,这有助于堆栈重写

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    // bad

    var log = function(msg) {

      console.log(msg);

    };

    // good

    var log = function log(msg) {

      console.log(msg);

    };

  • 注意:IE8以下还有一些关于命名函数表达式的怪癖。详情见http://kangax.github.io/nfe/
  • 访问器

  • 如果你创建访问函数使用getVal() 和 setVal(‘hello’)

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    // bad

    dragon.age();

    // good

    dragon.getAge();

    // bad

    dragon.age(25);

    // good

    dragon.setAge(25);

如果这个属性是boolean,使用isVal() 或者 hasVal()


1

2

3

4

5

6

7

8

9

// bad

if (!dragon.age()) {

  return false;

}

// good

if (!dragon.hasAge()) {

  return false;

}

.也可以使用get() 和 set()函数来创建,但是必须一致。


1

2

3

4

5

6

7

8

9

10

11

12

13

function Jedi(options) {

  options || (options = {});

  var lightsaber = options.lightsaber || ‘blue‘;

  this.set(‘lightsaber‘, lightsaber);

}

Jedi.prototype.set = function(key, val) {

  this[key] = val;

};

Jedi.prototype.get = function(key) {

  return this[key];

};

    • 构造器

    • 给原型对象添加方法,相比用新对象重写原型,重写原型会有继承问题。如果你要重写原型方法,请重写基础方法。

    • 1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      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有助于方法链

    • 1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      // bad

      Jedi.prototype.jump = function() {

        this.jumping = true;

        return true;

      };

      Jedi.prototype.setHeight = function(height) {

        this.height = height;

      };

      var luke = new Jedi();

      luke.jump(); // => true

      luke.setHeight(20); // => undefined

      // good

      Jedi.prototype.jump = function() {

        this.jumping = true;

        return this;

      };

      Jedi.prototype.setHeight = function(height) {

        this.height = height;

        return this;

      };

      var luke = new Jedi();

      luke.jump()

        .setHeight(20);

    • 可以重写常规的toString()方法。但必须保证可以成功运行并没有别的影响

    • 1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      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事件还是其他专用事件的,比如Backbone事件)用散列表来取代原始值。因为这将允许后续添加更多的数据载入事件而不用更新每个事件的处理程序。例如:

1

2

3

4

5

6

7

8

// bad

$(this).trigger(‘listingUpdated‘, listing.id);

...

$(this).on(‘listingUpdated‘, function(e, listingId) {

  // do something with listingId

});

更好的方式:


1

2

3

4

5

6

7

8

// good

$(this).trigger(‘listingUpdated‘, { listingId : listing.id });

...

$(this).on(‘listingUpdated‘, function(e, data) {

  // do something with data.listingId

});

模块

  • 模块应该以 “!”开始,以确保当模块忘记包含最后一个分号时,在脚本连接时不会报错。
  • 文档需要用驼峰法命名,同一文件内要用一样的名字以及要与单个输出相匹配。
  • 增加一个叫noConflict()的方法,使模块输出早期版本并返回。
  • 在模块开始的部位声明‘use strict‘

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    // 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对象变量前缀使用$

  • 1

    2

    3

    4

    5

    // bad

    var sidebar = $(‘.sidebar‘);

    // good

    var $sidebar = $(‘.sidebar‘);

  • jQuery缓存查找

  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    // 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‘)parent > child $(‘.sidebar > ul‘)jsPerf
    • 使用find来查找jQuery对象

    • 1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      // bad

      $(‘ul‘, ‘.sidebar‘).hide();

      // bad

      $(‘.sidebar‘).find(‘ul‘).hide();

      // good

      $(‘.sidebar ul‘).hide();

      // good

      $(‘.sidebar > ul‘).hide();

      // good

      $sidebar.find(‘ul‘).hide();

时间: 2024-10-17 16:08:17

【转】JavaScript 风格指南/编码规范(Airbnb公司版)的相关文章

浅谈 JavaScript 编程语言的编码规范

对于熟悉 C/C++ 或 Java 语言的工程师来说,JavaScript 显得灵活,简单易懂,对代码的格式的要求也相对松散.很容易学习,并运用到自己的代码中.也正因为这样,JavaScript 的编码规范也往往被轻视,开发过程中修修补补,最终也就演变成为后续维护人员的恶梦.软件存在的长期价值直接与编码的质量成比例.编码规范能帮助我们降低编程中不必要的麻烦.而 JavaScript 代码是直接发送给客户浏览器的,直接与客户见面,编码的质量更应该受到关注. 本文浅谈 JavaScript 编程中关

Google 开源项目风格指南阅读笔记(C++版)

虽说是编程风格指南,可是干货也不少,非常多C++的有用技术在里面. 头文件 通常每一个.cpp文件都相应一个.h文件:#define保护全部头文件都应该使用#define防止头文件被多重包括,为保证唯一性,头文件的命名应该根据所在项目源代码树的全部路径. 能用前置声明的地方尽量不用#include当一个头文件被包括的同一时候也引入了新的依赖,一旦该头文件被改动,代码就会被又一次编译,假设这个头文件又包括了其它头文件,这些文件的不论什么改变都将导致全部包括该头文件的代码被又一次编译. 假设头文件里

[转]JavaScript程序编码规范

原文:http://javascript.crockford.com/code.html 作者:Douglas Crockford 译文:http://www.yeeyan.com/articles/view/cloudwater/4042 译者:cloudwater 更新:2009-12-13 01:08:29 这是一套适用于JavaScript程序的编码规范.它基于Sun的Java程序编码规范.但进行了大幅度的修改, 因为JavaScript不是Java. 软件的长期价值直接源于其编码质量.

Google C++ 风格指南内容整理

之前一直没有全面的看过Google C++风格指南,现在很多公司进行C++开发都要求按照Google C++风格.在这个网站 http://zh-google-styleguide.readthedocs.org/en/latest/contents/  有人已经把其翻译成中文.为了便于以后查看,下面的内容完全是来自于这个网站,只是把多个网页的内容整理放在了一起. 1.      头文件: 通常每一个.cc文件都有一个对应的.h文件.也有一些常见例外,如单元测试代码和只包含main()函数的.c

最棒的 JavaScript 学习指南(2018版)

译者注:原文作者研究了近2.4万篇 JavaScript 文章得出这篇总结,全文包含学习指南.新人上手.Webpack.性能.基础概念.函数式编程.面试.教程案例.Async Await.并发.V8.机器学习.数据可视化.调试.单元测试等章节,非常适合用于对自己 JavaScript 技术栈的比对,用于查漏补缺,适合收藏阅读.有删减.文中如有错误,欢迎评论指出. 在过去的一年间(2017年),我们对比了近24000篇 JavaScript 文章,并从中挑选出了最好的55篇.我们做了这个目录,认为

阅读:《javascript权威指南》(笔记)

判断是否为NaN类型:x!=x //true 当且仅当x为NaN时,x才不等于自身. isNaN()//ture 参数为NaN或则非数字值,则返回true.false可判是否为断数字和字符串数字(如:"3"): js数字精度值极其接近0.1,如:0.411 - 0.401,期待结果0.01,实际结果结果为0.009999999999999953:通过"\"符号连接字符串,拼接html字符串更简洁,更高效: parseInt和parseFloat参数若为字符串,则该字

[转]Google的Java编程风格指南(Java编码规范)

这份文档是Google Java编程风格规范的完整定义.当且仅当一个Java源文件符合此文档中的规则, 我们才认为它符合Google的Java编程风格. 与其它的编程风格指南一样,这里所讨论的不仅仅是编码格式美不美观的问题, 同时也讨论一些约定及编码标准.然而,这份文档主要侧重于我们所普遍遵循的规则, 对于那些不是明确强制要求的,我们尽量避免提供意见. 1.1 术语说明 在本文档中,除非另有说明: 1.术语class可表示一个普通类,枚举类,接口或是annotation类型(@interface

Google的Java编程风格指南(Java编码规范)

这份文档是Google Java编程风格规范的完整定义.当且仅当一个Java源文件符合此文档中的规则, 我们才认为它符合Google的Java编程风格. 与其它的编程风格指南一样,这里所讨论的不仅仅是编码格式美不美观的问题, 同时也讨论一些约定及编码标准.然而,这份文档主要侧重于我们所普遍遵循的规则, 对于那些不是明确强制要求的,我们尽量避免提供意见. 1.1 术语说明 在本文档中,除非另有说明: 1.术语class可表示一个普通类,枚举类,接口或是annotation类型(@interface

JavaScript编码风格指南(中文版)

前言:程序语言的编码风格对于一个长期维护的软件非常重要,特别是在团队协作中.如果一个团队使用统一规范的编码分风格,可以提高团队的协作水平和工作效率.编程风格指南的核心是基本的格式化规则,这些规则决定了如何编写高水准的代码.本指南来自于<编写可维护的JavaScript>这本书,基于"Java语言编码规范"和Crockford的JavaScript编程规范,还有Nicbolas的一些个人经验和喜好.写作本文旨在加深自己印象,也为了更多人的了解到JS编码风格,提高自己的编码质量