JavaScript 最佳实践:帮你提升代码质量

rryth821 7年前
   <p>每天学一些新东西可以让一个理性之人走上不凡之路。而作为开发人员,不断的学习新东西则是我们工作的一部分, 不论这些新东西是不是来源于积极的学习经验。</p>    <p>在本篇教程中,我将指出一些重要的 JavaScript 最佳实践,让你不必去用另外一种艰难的方式来了解它们。准备好去升级你的代码吧!</p>    <h2><strong>1. 避免对全局作用域的污染</strong></h2>    <p>声明变量是一件很有趣的事情。有时候即使你不想这样做,但也有可能会定义出全局变量。在如今的浏览器中,全局变量都被存储在 window 对象中。而因为有许多的东西都在那个里面,所以你有可能把一些默认值都给覆盖掉了。</p>    <p>假设你有一个 HTML 文件,里面包含了一个 <script> 标记,而这个标记内含 (或者通过引用一个 JavaScript 文件而加载) 如下内容:</p>    <pre>  <code class="language-javascript">var foo = 42;  console.log(foo);</code></pre>    <p>这段代码很明显会让控制台输出 42。不过因为代码并不是放到一个函数里面去执行的,因此其执行的上下文就会是全局的那个。因此,变量就会被附加到 window 对象上。这就意味着 window.foo 的值也会是 42。</p>    <p>这样是挺危险的,因为你可以把已经存在的全局变量给覆盖掉:</p>    <pre>  <code class="language-javascript">function print () {     // do something  }  print();</code></pre>    <p>当执行 window.print (或者只是执行 print) 的时候, 它不会打开打印弹窗,因为我们已经将原生的打印弹窗逻辑给覆盖掉了。</p>    <p>解决这个问题的方案相当简单; 我们需要一个会在定义后立即被调用到的闭包函数, 如下所示:</p>    <pre>  <code class="language-javascript">// Declare an anonymous function  (function () {     var foo = 42;     console.log(window.foo);     // → undefined     console.log(foo);     // → 42  })();  //^ and call it immediately</code></pre>    <p>或者你也可以选择将 window 以及其它全局的东西(例如 document)都作为参数传给那个函数(这样做也可能对性能会有所提升):</p>    <pre>  <code class="language-javascript">(function (global, doc) {    global.setTimeout(function () {       doc.body.innerHTML = "Hello!";    }, 1000);  })(window, document);</code></pre>    <p>因此你得使用闭包函数来避免创建出什么全局的东西来。注意在这里因为要专注于代码本身,所以我不会在后面的代码片段中使用闭包函数。</p>    <p>提示:  browserify 是另外一种避免创建全局变量的方式。它采用了你在 Node.js 同样会用到的 require 函数的方式。</p>    <p>顺便说一下, Node.js 会自动将你的文件封装进函数里面。它们看起来先下面这样:</p>    <pre>  <code class="language-javascript">(function (exports, require, module, __filename, __dirname) {  // ...</code></pre>    <p>因此,如果你认为 require 函数式全局的,好吧,并不是。它无非就是一个 函数的参数 。</p>    <p>你知道吗?</p>    <p>因为 window 对象包含了所有的全局变量,又因为它自己也是全局的,因此 window 自己内部也引用了它自己:</p>    <pre>  <code class="language-javascript">window.window.window  // => Window {...}</code></pre>    <p>这是一位 window 对象是一个循环引用对象。下面展示了如何创建这样的一个对象:</p>    <pre>  <code class="language-javascript">// Create an object  var foo = {};  // Point a key value to the object itself  foo.bar = foo;  // The `foo` object just became a circular one:  foo.bar.bar.bar.bar  // → foo</code></pre>    <p>或者,为了展示你对 JavaScript 的无限的热爱之情,你可以当回发烧友,代码如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/da0e3a569b45bab6d5bc1d6690ccfdba.png"></p>    <p>是的,你可以几乎没完没了(也有可能会等到浏览器崩溃)的展开这个对象。</p>    <h2><strong>2. 好的 use strict 使用习惯</strong></h2>    <p>要严格使用 use strict! 这无非就是在你的代码中加了一行,给你的脚本增加更多的小把戏。</p>    <p>例如:</p>    <pre>  <code class="language-javascript">// This is bad, since you do create a global without having anyone to tell you  (function () {     a = 42;     console.log(a);     // → 42  })();  console.log(a);  // → 42</code></pre>    <p>使用 use strict, 你就可以获取到更多一点的错误信息:</p>    <pre>  <code class="language-javascript">(function () {     "use strict";     a = 42;     // Error: Uncaught ReferenceError: a is not defined  })();</code></pre>    <p>你可能想知道为什么可以将 "use strict" 放在封装函数的外面。这的确是可以的,不过这样它就会被应用到全局。这还不是太坏,但是如果有代码是来自于其它的库,或者你要把所有的东西都打包到一个文件里面去的话,这样做就会有影响的。</p>    <h2><strong>3. 严格相等</strong></h2>    <p>这个比较简短。如果你在 JavaScript 中 (像其它的编程语言中那样)使用 == 来比较 a 和 b,可能会发现其运行的方式有点怪: 如果你有一个字符串和一个数字如下,它们会相等 (==):</p>    <pre>  <code class="language-javascript">"42" == 42  // → true</code></pre>    <p>对于一些明显的缘故 (例如验证操作), 最好就是使用严格等于(===):</p>    <pre>  <code class="language-javascript">"42" === 42  // → false</code></pre>    <h2><strong>4. 使用 && 和 || 来制造点小把戏</strong></h2>    <p>根据你需要做的事情,你可以使用逻辑操作符来让代码更简短。</p>    <p>取默认值</p>    <pre>  <code class="language-javascript">"" || "foo"  // → "foo"  undefined || 42  // → 42  // Note that if you want to handle 0 there, you need  // to check if a number was provided:  var a = 0;  a || 42  // → 42  // This is a ternary operator—works like an inline if-else statement  var b = typeof a === "number" ? a : 42;  // → 0</code></pre>    <p>不用拿 if 表达式来检查某些东西是不是为真的,你也可以简单地这样做:</p>    <pre>  <code class="language-javascript">expr && doSomething();    // Instead of:</code></pre>    <pre>  <code class="language-javascript">if (expr) {     doSomething();  }</code></pre>    <p>如果你需要通过 doSomething(): 来决定返回的结果,这样做更酷:</p>    <pre>  <code class="language-javascript">function doSomething () {     return { foo: "bar" };  }</code></pre>    <pre>  <code class="language-javascript">var expr = true;</code></pre>    <pre>  <code class="language-javascript">var res = expr && doSomething();  res && console.log(res);  // → { foo: "bar" }</code></pre>    <p>你可能不会赞同我在这方面的看法,但像我说的这样做其实效果更理想。如果你并不想像这样来对你的代码进行混淆,但其实这就是那些 JavaScript 简化器实际会做的事情。</p>    <p>如果你来问我,我会说这样做虽然让代码更加简短了,但仍然是可读的。</p>    <h2><strong>5. 对值的类型进行转化</strong></h2>    <p>有几种方法可以根据你的想法来进行转化。最常用的方式有如下这些:</p>    <pre>  <code class="language-javascript">// From anything to a number    var foo = "42";  var myNumber = +foo; // shortcut for Number(foo)  // → 42    // Tip: you can convert it directly into a negative number  var negativeFoo = -foo; // or -Number(foo)  // → -42    // From object to array  // Tip: `arguments` is an object and in general you want to use it as array  var args = { 0: "foo", 1: "bar", length: 2 };  Array.prototype.slice.call(args)  // → [ 'foo', 'bar' ]    // Anything to boolean  /// Non non p is a boolean p  var t = 1;  var f = 0;  !!t  // → true  !!f  // → false    /// And non-p is a boolean non-p  !t  // → false  !f  // → true    // Anything to string  var foo = 42;  "" + foo // shortcut for String(foo)  // → "42"    foo = { hello: "world" };  JSON.stringify(foo);  // → '{ "hello":"world" }'    JSON.stringify(foo, null, 4); // beautify the things  // →  // '{  //    "hello": "world"  // }'    // Note you cannot JSON.stringify circular structures  JSON.stringify(window);  // ⚠ TypeError: JSON.stringify cannot serialize cyclic structures.</code></pre>    <h2><strong>6. 代码风格/风格指南</strong></h2>    <p>在新的项目中要让所有的文件都遵循相同的代码风格。对于现有的项目,就使用现有的代码风格, 除非你就只是决定要变一变它的风格 <em>(提示: 同你的搭档就此进行一下讨论)</em> 。甚至你要创建和记录你自己的代码风格,然后一直去遵循它。</p>    <p>现有的一些不同的代码风格如下:</p>    <ul>     <li> <p>Google JavaScript 风格指南</p> </li>     <li> <p>airbnb/javascript</p> </li>     <li> <p>... 也还有其它的一些</p> </li>    </ul>    <h2><strong>额外的福利小提示:</strong></h2>    <p>你应该记住的其它一些重要的 JavaScript 最佳实践就是那些能帮助你对代码进行格式化的工具。下面是其中的一些:</p>    <ul>     <li> <p>js-beautify : 美化你的代码</p> </li>     <li> <p>UglifyJS(2) : 混淆/最小化你的代码</p> </li>     <li> <p>jshint : 检测 JavaScript 代码中的错误或者潜在问题</p> </li>     <li> <p>jscs : 可以配置的样式指南检测器</p> </li>    </ul>    <p>最后一个就是: 不要总是 console.log,要 对你的代码进行调试 。</p>    <p> </p>    <p> </p>    <p>来自:https://www.oschina.net/translate/javascript-best-practices</p>    <p> </p>