<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 核心 ## 為什么不要使用 `eval` `eval` 函數會在當前作用域中執行一段 JavaScript 代碼字符串。 ``` var foo = 1; function test() { var foo = 2; eval('foo = 3'); return foo; } test(); // 3 foo; // 1 ``` 但是 `eval` 只在被**直接**調用并且調用函數就是 `eval` 本身時,才在當前作用域中執行。 ``` var foo = 1; function test() { var foo = 2; var bar = eval; bar('foo = 3'); return foo; } test(); // 2 foo; // 3 ``` **[譯者注](http://cnblogs.com/sanshi/):**上面的代碼等價于在全局作用域中調用 `eval`,和下面兩種寫法效果一樣: ``` // 寫法一:直接調用全局作用域下的 foo 變量 var foo = 1; function test() { var foo = 2; window.foo = 3; return foo; } test(); // 2 foo; // 3 // 寫法二:使用 call 函數修改 eval 執行的上下文為全局作用域 var foo = 1; function test() { var foo = 2; eval.call(window, 'foo = 3'); return foo; } test(); // 2 foo; // 3 ``` 在**任何情況下**我們都應該避免使用 `eval` 函數。99.9% 使用 `eval` 的場景都有**不使用** `eval` 的解決方案。 ### 偽裝的 `eval` [定時函數](#other.timeouts) `setTimeout` 和 `setInterval` 都可以接受字符串作為它們的第一個參數。 這個字符串**總是**在全局作用域中執行,因此 `eval` 在這種情況下沒有被直接調用。 ### 安全問題 `eval` 也存在安全問題,因為它會執行**任意**傳給它的代碼, 在代碼字符串未知或者是來自一個不信任的源時,絕對不要使用 `eval` 函數。 ### 結論 絕對不要使用 `eval`,任何使用它的代碼都會在它的工作方式,性能和安全性方面受到質疑。 如果一些情況必須使用到 `eval` 才能正常工作,首先它的設計會受到質疑,這**不應該**是首選的解決方案, 一個更好的不使用 `eval` 的解決方案應該得到充分考慮并優先采用。 ## `undefined` 和 `null` JavaScript 有兩個表示‘空’的值,其中比較有用的是 `undefined`。 ### `undefined` 的值 `undefined` 是一個值為 `undefined` 的類型。 這個語言也定義了一個全局變量,它的值是 `undefined`,這個變量也被稱為 `undefined`。 但是這個變量**不是**一個常量,也不是一個關鍵字。這意味著它的_值_可以輕易被覆蓋。 **ES5 提示:** 在 ECMAScript 5 的嚴格模式下,`undefined` **不再是** _可寫_的了。 但是它的名稱仍然可以被隱藏,比如定義一個函數名為 `undefined`。 下面的情況會返回 `undefined` 值: * 訪問未修改的全局變量 `undefined`。 * 由于沒有定義 `return` 表達式的函數隱式返回。 * `return` 表達式沒有顯式的返回任何內容。 * 訪問不存在的屬性。 * 函數參數沒有被顯式的傳遞值。 * 任何被設置為 `undefined` 值的變量。 ### 處理 `undefined` 值的改變 由于全局變量 `undefined` 只是保存了 `undefined` 類型實際_值_的副本, 因此對它賦新值**不會**改變類型 `undefined` 的值。 然而,為了方便其它變量和 `undefined` 做比較,我們需要事先獲取類型 `undefined` 的值。 為了避免可能對 `undefined` 值的改變,一個常用的技巧是使用一個傳遞到[匿名包裝器](#function.scopes)的額外參數。 在調用時,這個參數不會獲取任何值。 ``` var undefined = 123; (function(something, foo, undefined) { // 局部作用域里的 undefined 變量重新獲得了 `undefined` 值 })('Hello World', 42); ``` 另外一種達到相同目的方法是在函數內使用變量聲明。 ``` var undefined = 123; (function(something, foo) { var undefined; ... })('Hello World', 42); ``` 這里唯一的區別是,在壓縮后并且函數內沒有其它需要使用 `var` 聲明變量的情況下,這個版本的代碼會多出 4 個字節的代碼。 **[譯者注](http://cnblogs.com/sanshi/):**這里有點繞口,其實很簡單。如果此函數內沒有其它需要聲明的變量,那么 `var` 總共 4 個字符(包含一個空白字符) 就是專門為 `undefined` 變量準備的,相比上個例子多出了 4 個字節。 ### `null` 的用處 JavaScript 中的 `undefined` 的使用場景類似于其它語言中的 _null_,實際上 JavaScript 中的 `null` 是另外一種數據類型。 它在 JavaScript 內部有一些使用場景(比如聲明原型鏈的終結 `Foo.prototype = null`),但是大多數情況下都可以使用 `undefined` 來代替。 ## 自動分號插入 盡管 JavaScript 有 C 的代碼風格,但是它**不**強制要求在代碼中使用分號,實際上可以省略它們。 JavaScript 不是一個沒有分號的語言,恰恰相反上它需要分號來就解析源代碼。 因此 JavaScript 解析器在遇到由于缺少分號導致的解析錯誤時,會**自動**在源代碼中插入分號。 ``` var foo = function() { } // 解析錯誤,分號丟失 test() ``` 自動插入分號,解析器重新解析。 ``` var foo = function() { }; // 沒有錯誤,解析繼續 test() ``` 自動的分號插入被認為是 JavaScript 語言**最大**的設計缺陷之一,因為它_能_改變代碼的行為。 ### 工作原理 下面的代碼沒有分號,因此解析器需要自己判斷需要在哪些地方插入分號。 ``` (function(window, undefined) { function test(options) { log('testing!') (options.list || []).forEach(function(i) { }) options.value.test( 'long string to pass here', 'and another long string to pass' ) return { foo: function() {} } } window.test = test })(window) (function(window) { window.someLibrary = {} })(window) ``` 下面是解析器"猜測"的結果。 ``` (function(window, undefined) { function test(options) { // 沒有插入分號,兩行被合并為一行 log('testing!')(options.list || []).forEach(function(i) { }); // <- 插入分號 options.value.test( 'long string to pass here', 'and another long string to pass' ); // <- 插入分號 return; // <- 插入分號, 改變了 return 表達式的行為 { // 作為一個代碼段處理 foo: function() {} }; // <- 插入分號 } window.test = test; // <- 插入分號 // 兩行又被合并了 })(window)(function(window) { window.someLibrary = {}; // <- 插入分號 })(window); //<- 插入分號 ``` **注意:** JavaScript 不能正確的處理 `return` 表達式緊跟換行符的情況, 雖然這不能算是自動分號插入的錯誤,但這確實是一種不希望的副作用。 解析器顯著改變了上面代碼的行為,在另外一些情況下也會做出**錯誤的處理**。 ### 前置括號 在前置括號的情況下,解析器**不會**自動插入分號。 ``` log('testing!') (options.list || []).forEach(function(i) {}) ``` 上面代碼被解析器轉換為一行。 ``` log('testing!')(options.list || []).forEach(function(i) {}) ``` `log` 函數的執行結果**極大**可能**不是**函數;這種情況下就會出現 `TypeError` 的錯誤,詳細錯誤信息可能是 `undefined is not a function`。 ### 結論 建議**絕對**不要省略分號,同時也提倡將花括號和相應的表達式放在一行, 對于只有一行代碼的 `if` 或者 `else` 表達式,也不應該省略花括號。 這些良好的編程習慣不僅可以提到代碼的一致性,而且可以防止解析器改變代碼行為的錯誤處理。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看