用更合理的方式写 JavaScript

kart 9年前
   <h2>类型</h2>    <p><strong>原始值</strong>: 存取直接作用于它自身。</p>    <pre>  <code class="language-javascript">var foo = 1;  var bar = foo;    bar = 9;    console.log(foo, bar); // => 1, 9</code></pre>    <ul>     <li><code>string</code></li>     <li><code>number</code></li>     <li><code>boolean</code></li>     <li><code>null</code></li>     <li><code>undefined</code></li>    </ul>    <p><strong>复杂类型</strong>: 存取时作用于它自身值的引用。</p>    <pre>  <code class="language-javascript">var foo = [1, 2];  var bar = foo;    bar[0] = 9;    console.log(foo[0], bar[0]); // => 9, 9</code></pre>    <ul>     <li><code>object</code></li>     <li><code>array</code></li>     <li><code>function</code></li>    </ul>    <h2>对象</h2>    <p>使用直接量创建对象。</p>    <pre>  <code class="language-javascript">// bad  var item = new Object();    // good  var item = {};</code></pre>    <p>不要使用<a href="/misc/goto?guid=4959670115886774139">保留字</a>作为键名,它们在 IE8 下不工作。<a href="/misc/goto?guid=4959670115976385304">更多信息</a>。</p>    <pre>  <code class="language-javascript">// bad  var superman = {    default: { clark: 'kent' },    private: true  };    // good  var superman = {    defaults: { clark: 'kent' },    hidden: true  };</code></pre>    <p>使用同义词替换需要使用的保留字。</p>    <pre>  <code class="language-javascript">// bad  var superman = {    class: 'alien'  };    // bad  var superman = {    klass: 'alien'  };    // good  var superman = {    type: 'alien'  };</code></pre>    <h2>数组</h2>    <p>使用直接量创建数组。</p>    <pre>  <code class="language-javascript">// bad  var items = new Array();    // good  var items = [];</code></pre>    <p>向数组增加元素时使用 Array#push 来替代直接赋值。</p>    <pre>  <code class="language-javascript">var someStack = [];      // bad  someStack[someStack.length] = 'abracadabra';    // good  someStack.push('abracadabra');</code></pre>    <p>当你需要拷贝数组时,使用 Array#slice。<a href="/misc/goto?guid=4959645689073816137">jsPerf</a></p>    <pre>  <code class="language-javascript">var len = items.length;  var itemsCopy = [];  var i;    // bad  for (i = 0; i < len; i++) {    itemsCopy[i] = items[i];  }    // good  itemsCopy = items.slice();</code></pre>    <p>使用 Array#slice 将类数组对象转换成数组。</p>    <pre>  <code class="language-javascript">function trigger() {    var args = Array.prototype.slice.call(arguments);    ...  }  </code></pre>    <h2>字符串</h2>    <p>使用单引号 <code>''</code> 包裹字符串。</p>    <pre>  <code class="language-javascript">// bad  var name = "Bob Parr";    // good  var name = 'Bob Parr';    // bad  var fullName = "Bob " + this.lastName;    // good  var fullName = 'Bob ' + this.lastName;</code></pre>    <p>超过 100 个字符的字符串应该使用连接符写成多行。</p>    <p>注:若过度使用,通过连接符连接的长字符串可能会影响性能。<a href="/misc/goto?guid=4959645689167330371">jsPerf</a> & <a href="/misc/goto?guid=4959645689251598662">讨论</a>.</p>    <pre>  <code class="language-javascript">// 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.';</code></pre>    <p>程序化生成的字符串使用 Array#join 连接而不是使用连接符。尤其是 IE 下:<a href="/misc/goto?guid=4959670116169870721">jsPerf</a>.</p>    <pre>  <code class="language-javascript">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>';  }</code></pre>    <h2>函数</h2>    <p>函数表达式:</p>    <pre>  <code class="language-javascript">// 匿名函数表达式  var anonymous = function() {    return true;  };    // 命名函数表达式  var named = function named() {    return true;  };    // 立即调用的函数表达式(IIFE)  (function() {    console.log('Welcome to the Internet. Please follow me.');  })();</code></pre>    <p>永远不要在一个非函数代码块(if、while 等)中声明一个函数,把那个函数赋给一个变量。浏览器允许你这么做,但它们的解析表现不一致。</p>    <p><strong>注:</strong> ECMA-262 把 <code>块</code> 定义为一组语句。函数声明不是语句。<a href="/misc/goto?guid=4959670116251216261">阅读对 ECMA-262 这个问题的说明</a>。</p>    <pre>  <code class="language-javascript">// bad  if (currentUser) {    function test() {      console.log('Nope.');    }  }    // good  var test;  if (currentUser) {    test = function test() {      console.log('Yup.');    };  }</code></pre>    <p>永远不要把参数命名为 <code>arguments</code>。这将取代函数作用域内的 <code>arguments</code> 对象。</p>    <pre>  <code class="language-javascript">// bad  function nope(name, options, arguments) {    // ...stuff...  }    // good  function yup(name, options, args) {    // ...stuff...  }</code></pre>    <h2>属性</h2>    <p>使用 <code>.</code> 来访问对象的属性。</p>    <pre>  <code class="language-javascript">var luke = {    jedi: true,    age: 28  };    // bad  var isJedi = luke['jedi'];    // good  var isJedi = luke.jedi;</code></pre>    <p>当通过变量访问属性时使用中括号 <code>[]</code>。</p>    <pre>  <code class="language-javascript">var luke = {    jedi: true,    age: 28  };    function getProp(prop) {    return luke[prop];  }    var isJedi = getProp('jedi');</code></pre>    <h2>变量</h2>    <p>总是使用 <code>var</code> 来声明变量。不这么做将导致产生全局变量。我们要避免污染全局命名空间。</p>    <pre>  <code class="language-javascript">// bad  superPower = new SuperPower();    // good  var superPower = new SuperPower();</code></pre>    <p>使用 <code>var</code> 声明每一个变量。 这样做的好处是增加新变量将变的更加容易,而且你永远不用再担心调换错 <code>;</code> 跟 <code>,</code>。</p>    <pre>  <code class="language-javascript">// 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';</code></pre>    <p>最后再声明未赋值的变量。当你需要引用前面的变量赋值时这将变的很有用。</p>    <pre>  <code class="language-javascript">// 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;</code></pre>    <p>在作用域顶部声明变量。这将帮你避免变量声明提升相关的问题。</p>    <pre>  <code class="language-javascript">// 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;  }</code></pre>    <h2>提升</h2>    <p>变量声明会提升至作用域顶部,但赋值不会。</p>    <pre>  <code class="language-javascript">// 我们知道这样不能正常工作(假设这里没有名为 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;  }</code></pre>    <p>匿名函数表达式会提升它们的变量名,但不会提升函数的赋值。</p>    <pre>  <code class="language-javascript">function example() {    console.log(anonymous); // => undefined      anonymous(); // => TypeError anonymous is not a function      var anonymous = function() {      console.log('anonymous function expression');    };  }</code></pre>    <p>命名函数表达式会提升变量名,但不会提升函数名或函数体。</p>    <pre>  <code class="language-javascript">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');    }  }</code></pre>    <p>函数声明提升它们的名字和函数体。</p>    <pre>  <code class="language-javascript">function example() {    superPower(); // => Flying      function superPower() {      console.log('Flying');    }  }</code></pre>    <p>了解更多信息在 <a href="/misc/goto?guid=4959645689398661505">JavaScript Scoping & Hoisting</a> by <a href="/misc/goto?guid=4958535186876491748">Ben Cherry</a>.</p>    <h2>比较运算符 & 等号</h2>    <p>优先使用 <code>===</code> 和 <code>!==</code> 而不是 <code>==</code> 和 <code>!=</code>.</p>    <p>条件表达式例如 <code>if</code> 语句通过抽象方法 <code>ToBoolean</code> 强制计算它们的表达式并且总是遵守下面的规则:</p>    <pre>  <code class="language-javascript">if ([0]) {    // true    // 一个数组就是一个对象,对象被计算为 true  }</code></pre>    <ul>     <li><strong>对象</strong> 被计算为 <strong>true</strong></li>     <li><strong>Undefined</strong> 被计算为 <strong>false</strong></li>     <li><strong>Null</strong> 被计算为 <strong>false</strong></li>     <li><strong>布尔值</strong> 被计算为 <strong>布尔的值</strong></li>     <li><strong>数字</strong> 如果是 <strong>+0、-0 或 NaN</strong> 被计算为 <strong>false</strong>,否则为 <strong>true</strong></li>     <li><strong>字符串</strong> 如果是空字符串 <code>''</code> 被计算为 <strong>false</strong>,否则为 <strong>true</strong></li>    </ul>    <p>使用快捷方式。</p>    <pre>  <code class="language-javascript">// bad  if (name !== '') {    // ...stuff...  }    // good  if (name) {    // ...stuff...  }    // bad  if (collection.length > 0) {    // ...stuff...  }    // good  if (collection.length) {    // ...stuff...  }</code></pre>    <p>了解更多信息在 <a href="/misc/goto?guid=4959645689511754568">Truth Equality and JavaScript</a> by Angus Croll.</p>    <h2>块</h2>    <p>使用大括号包裹所有的多行代码块。</p>    <pre>  <code class="language-javascript">// bad  if (test)    return false;    // good  if (test) return false;    // good  if (test) {    return false;  }    // bad  function() { return false; }    // good  function() {    return false;  }</code></pre>    <p>如果通过 <code>if</code> 和 <code>else</code> 使用多行代码块,把 <code>else</code> 放在 <code>if</code> 代码块关闭括号的同一行。</p>    <pre>  <code class="language-javascript">// bad  if (test) {    thing1();    thing2();  }  else {    thing3();  }    // good  if (test) {    thing1();    thing2();  } else {    thing3();  }  </code></pre>    <h2>注释</h2>    <p>使用 <code>/** ... */</code> 作为多行注释。包含描述、指定所有参数和返回值的类型和值。</p>    <pre>  <code class="language-javascript">// 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;  }</code></pre>    <p>使用 <code>//</code> 作为单行注释。在评论对象上面另起一行使用单行注释。在注释前插入空行。</p>    <pre>  <code class="language-javascript">// 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;  }</code></pre>    <p>给注释增加 <code>FIXME</code> 或 <code>TODO</code> 的前缀可以帮助其他开发者快速了解这是一个需要复查的问题,或是给需要实现的功能提供一个解决方式。这将有别于常见的注释,因为它们是可操作的。使用 <code>FIXME -- need to figure this out</code> 或者 <code>TODO -- need to implement</code>。</p>    <p>使用 <code>// FIXME:</code> 标注问题。</p>    <pre>  <code class="language-javascript">function Calculator() {      // FIXME: shouldn't use a global here    total = 0;      return this;  }</code></pre>    <p>使用 <code>// TODO:</code> 标注问题的解决方式。</p>    <pre>  <code class="language-javascript">function Calculator() {      // TODO: total should be configurable by an options param    this.total = 0;      return this;  }</code></pre>    <h2>空白</h2>    <p>使用 2 个空格作为缩进。</p>    <pre>  <code class="language-javascript">// bad  function() {  ∙∙∙∙var name;  }    // bad  function() {  ∙var name;  }    // good  function() {  ∙∙var name;  }</code></pre>    <p>在大括号前放一个空格。</p>    <pre>  <code class="language-javascript">// 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'  });</code></pre>    <p>在控制语句(<code>if</code>、<code>while</code> 等)的小括号前放一个空格。在函数调用及声明中,不在函数的参数列表前加空格。</p>    <pre>  <code class="language-javascript">// bad  if(isJedi) {    fight ();  }    // good  if (isJedi) {    fight();  }    // bad  function fight () {    console.log ('Swooosh!');  }    // good  function fight() {    console.log('Swooosh!');  }</code></pre>    <p>使用空格把运算符隔开。</p>    <pre>  <code class="language-javascript">// bad  var x=y+5;    // good  var x = y + 5;</code></pre>    <p>在文件末尾插入一个空行。</p>    <pre>  <code class="language-javascript">// bad  (function(global) {    // ...stuff...  })(this);</code></pre>    <pre>  <code class="language-javascript">// bad  (function(global) {    // ...stuff...  })(this);↵  ↵</code></pre>    <pre>  <code class="language-javascript">// good  (function(global) {    // ...stuff...  })(this);↵</code></pre>    <p>在使用长方法链时进行缩进。使用前面的点 <code>.</code> 强调这是方法调用而不是新语句。</p>    <pre>  <code class="language-javascript">// 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);</code></pre>    <p>在块末和新语句前插入空行。</p>    <pre>  <code class="language-javascript">// 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;</code></pre>    <h2>逗号</h2>    <p>行首逗号: <strong>不需要</strong>。</p>    <pre>  <code class="language-javascript">// 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'  };</code></pre>    <p>额外的行末逗号:<strong>不需要</strong>。这样做会在 IE6/7 和 IE9 怪异模式下引起问题。同样,多余的逗号在某些 ES3 的实现里会增加数组的长度。在 ES5 中已经澄清了 (<a href="/misc/goto?guid=4959645689631666194">source</a>):</p>    <blockquote>     <p>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.</p>    </blockquote>    <pre>  <code class="language-javascript">  // bad    var hero = {      firstName: 'Kevin',      lastName: 'Flynn',    };      var heroes = [      'Batman',      'Superman',    ];      // good    var hero = {      firstName: 'Kevin',      lastName: 'Flynn'    };      var heroes = [      'Batman',      'Superman'    ];</code></pre>    <h2>分号</h2>    <p><strong>使用分号。</strong></p>    <pre>  <code class="language-javascript">// bad  (function() {    var name = 'Skywalker'    return name  })()    // good  (function() {    var name = 'Skywalker';    return name;  })();    // good (防止函数在两个 IIFE 合并时被当成一个参数  ;(function() {    var name = 'Skywalker';    return name;  })();</code></pre>    <p><a href="/misc/goto?guid=4959670116454043979">了解更多</a>.</p>    <h2>类型转换</h2>    <p>在语句开始时执行类型转换。</p>    <p>字符串:</p>    <pre>  <code class="language-javascript">//  => 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';</code></pre>    <p>使用 <code>parseInt</code> 转换数字时总是带上类型转换的基数。</p>    <pre>  <code class="language-javascript">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);</code></pre>    <p>如果因为某些原因 <code>parseInt</code> 成为你所做的事的瓶颈而需要使用位操作解决<a href="/misc/goto?guid=4959645689728396331">性能问题</a>时,留个注释说清楚原因和你的目的。</p>    <pre>  <code class="language-javascript">// 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;</code></pre>    <blockquote>     <p><strong>注:</strong> 小心使用位操作运算符。数字会被当成 <a href="/misc/goto?guid=4959645689822196207">64 位值</a>,但是位操作运算符总是返回 32 位的整数(<a href="/misc/goto?guid=4959645689910417520">source</a>)。位操作处理大于 32 位的整数值时还会导致意料之外的行为。<a href="/misc/goto?guid=4959645689985214752">讨论</a>。最大的 32 位整数是 2,147,483,647:</p>    </blockquote>    <pre>  <code class="language-javascript">2147483647 >> 0 //=> 2147483647  2147483648 >> 0 //=> -2147483648  2147483649 >> 0 //=> -2147483647</code></pre>    <p>布尔:</p>    <pre>  <code class="language-javascript">var age = 0;    // bad  var hasAge = new Boolean(age);    // good  var hasAge = Boolean(age);    // good  var hasAge = !!age;</code></pre>    <h2>命名规则</h2>    <p>避免单字母命名。命名应具备描述性。</p>    <pre>  <code class="language-javascript">// bad  function q() {    // ...stuff...  }    // good  function query() {    // ..stuff..  }</code></pre>    <p>使用驼峰式命名对象、函数和实例。</p>    <pre>  <code class="language-javascript">// bad  var OBJEcttsssss = {};  var this_is_my_object = {};  var o = {};  function c() {}    // good  var thisIsMyObject = {};  function thisIsMyFunction() {}</code></pre>    <p>使用帕斯卡式命名构造函数或类。</p>    <pre>  <code class="language-javascript">// 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'  });</code></pre>    <p>使用下划线 <code>_</code> 开头命名私有属性。</p>    <pre>  <code class="language-javascript">// bad  this.__firstName__ = 'Panda';  this.firstName_ = 'Panda';    // good  this._firstName = 'Panda';</code></pre>    <p>使用 <code>_this</code> 保存 <code>this</code> 的引用。</p>    <pre>  <code class="language-javascript">// 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);    };  }</code></pre>    <p>给函数命名。这在做堆栈轨迹时很有帮助。</p>    <pre>  <code class="language-javascript">// bad  var log = function(msg) {    console.log(msg);  };    // good  var log = function log(msg) {    console.log(msg);  };</code></pre>    <p><strong>注:</strong> IE8 及以下版本对命名函数表达式的处理有些怪异。了解更多信息到 <a href="/misc/goto?guid=4958833746252848138">http://kangax.github.io/nfe/</a>。</p>    <p>如果你的文件导出一个类,你的文件名应该与类名完全相同。</p>    <pre>  <code class="language-javascript">// file contents  class CheckBox {    // ...  }  module.exports = CheckBox;    // in some other file  // bad  var CheckBox = require('./checkBox');    // bad  var CheckBox = require('./check_box');    // good  var CheckBox = require('./CheckBox');</code></pre>    <h2>存取器</h2>    <p>属性的存取函数不是必须的。</p>    <p>如果你需要存取函数时使用 <code>getVal()</code> 和 <code>setVal('hello')</code>。</p>    <pre>  <code class="language-javascript">// bad  dragon.age();    // good  dragon.getAge();    // bad  dragon.age(25);    // good  dragon.setAge(25);</code></pre>    <p>如果属性是布尔值,使用 <code>isVal()</code> 或 <code>hasVal()</code>。</p>    <pre>  <code class="language-javascript">// bad  if (!dragon.age()) {    return false;  }    // good  if (!dragon.hasAge()) {    return false;  }</code></pre>    <p>创建 get() 和 set() 函数是可以的,但要保持一致。</p>    <pre>  <code class="language-javascript">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];  };</code></pre>    <h2>构造函数</h2>    <p>给对象原型分配方法,而不是使用一个新对象覆盖原型。覆盖原型将导致继承出现问题:重设原型将覆盖原有原型!</p>    <pre>  <code class="language-javascript">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');  };</code></pre>    <p>方法可以返回 <code>this</code> 来实现方法链式使用。</p>    <pre>  <code class="language-javascript">// 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);</code></pre>    <p>写一个自定义的 <code>toString()</code> 方法是可以的,但是确保它可以正常工作且不会产生副作用。</p>    <pre>  <code class="language-javascript">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();  };</code></pre>    <h2>事件</h2>    <p>当给事件附加数据时(无论是 DOM 事件还是私有事件),传入一个哈希而不是原始值。这样可以让后面的贡献者增加更多数据到事件数据而无需找出并更新事件的每一个处理器。例如,不好的写法:</p>    <pre>  <code class="language-javascript">// bad  $(this).trigger('listingUpdated', listing.id);    ...    $(this).on('listingUpdated', function(e, listingId) {    // do something with listingId  });</code></pre>    <p>更好的写法:</p>    <pre>  <code class="language-javascript">// good  $(this).trigger('listingUpdated', { listingId : listing.id });    ...    $(this).on('listingUpdated', function(e, data) {    // do something with data.listingId  });</code></pre>    <h2>模块</h2>    <p>模块应该以 <code>!</code> 开始。这样确保了当一个不好的模块忘记包含最后的分号时,在合并代码到生产环境后不会产生错误。<a href="/misc/goto?guid=4959670116680366168">详细说明</a></p>    <p>文件应该以驼峰式命名,并放在同名的文件夹里,且与导出的名字一致。</p>    <p>增加一个名为 <code>noConflict()</code> 的方法来设置导出的模块为前一个版本并返回它。</p>    <p>永远在模块顶部声明 <code>'use strict';</code>。</p>    <pre>  <code class="language-javascript">// 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);</code></pre>    <h2>jQuery</h2>    <p>使用 <code>$</code> 作为存储 jQuery 对象的变量名前缀。</p>    <pre>  <code class="language-javascript">// bad  var sidebar = $('.sidebar');    // good  var $sidebar = $('.sidebar');</code></pre>    <p>缓存 jQuery 查询。</p>    <pre>  <code class="language-javascript">// 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'    });  }</code></pre>    <p>对 DOM 查询使用层叠 <code>$('.sidebar ul')</code> 或 父元素 > 子元素 <code>$('.sidebar > ul')</code>。 <a href="/misc/goto?guid=4959670116764411379">jsPerf</a></p>    <p>对有作用域的 jQuery 对象查询使用 <code>find</code>。</p>    <pre>  <code class="language-javascript">// bad  $('ul', '.sidebar').hide();    // bad  $('.sidebar').find('ul').hide();    // good  $('.sidebar ul').hide();    // good  $('.sidebar > ul').hide();    // good  $sidebar.find('ul').hide();</code></pre>    <h2>ECMAScript 5 兼容性</h2>    <p>参考 <a href="/misc/goto?guid=4959670116842294972">Kangax</a> 的 ES5 <a href="/misc/goto?guid=4958336441557726449">兼容表</a>.</p>    <h2>测试</h2>    <p><strong>Yup.</strong></p>    <pre>  <code class="language-javascript">function() {    return true;  }</code></pre>    <p>来自:https://github.com/sivan/javascript-style-guide/blob/master/es5/README.md</p>