JavaScript >> Javascript 文檔 >  >> JavaScript

是時候開始使用 JavaScript 嚴格模式了

ECMAScript 5 為 JavaScript 引入了嚴格模式。其目的是允許開發人員選擇加入“更好”的 JavaScript 版本,其中一些最常見和最嚴重的錯誤以不同的方式處理。有一段時間,我持懷疑態度,尤其是最初只有一個瀏覽器(Firefox)支持嚴格模式。快進到今天,每個主流瀏覽器都在其最新版本中支持嚴格模式,包括 Internet Explorer 10 和 Opera 12。是時候開始使用嚴格模式了。

它有什麼作用?

嚴格模式對 JavaScript 的運行方式進行了很多更改,我將它們分為兩類:明顯的和微妙的。細微的變化旨在解決細微的問題,我不打算在這裡深入研究;如果您對這些細節感興趣,請參閱 Dmitry Soshnikov 的優秀作品 ECMA-262-5 詳細信息。第 2 章嚴格模式 1 .我更感興趣的是談論明顯的變化:在使用嚴格模式之前你應該知道的那些,以及最有可能對你幫助最大的那些。

在進入特定功能之前,請記住,嚴格模式的目標之一是允許更快地調試問題。幫助開發人員調試的最好方法是在某些模式發生時拋出錯誤,而不是默默地失敗或行為異常(今天 JavaScript 在嚴格模式之外所做的)。嚴格模式的代碼會拋出更多的錯誤,這是一件好事,因為它很快就會引起人們注意應該立即修復的事情。

消除與

首先,嚴格模式消除了 with 陳述。它現在被認為是無效的 JavaScript 語法,當它出現在嚴格模式代碼中時會拋出語法錯誤。所以使用嚴格模式的第一步:確保你沒有使用 with .

// Causes a syntax error in strict mode
with (location) {
    alert(href);
}

防止意外的全局變量

接下來,必須先聲明變量,然後才能對其進行賦值。如果沒有嚴格模式,為未聲明的變量賦值會自動創建一個具有該名稱的全局變量。這是 JavaScript 中最常見的錯誤之一。在嚴格模式下,嘗試這樣做會引發錯誤。

// Throws an error in strict mode
(function() {

    someUndeclaredVar = "foo";

}());

消除這種強制

另一個重要的變化是 this -null 的值 或 undefined 不再被強製到全球。相反,this 保持其原始值,因此可能會導致某些代碼取決於強制中斷。例如:

window.color = "red";
function sayColor() {
    alert(this.color);
}

// Throws an error in strict mode, "red" otherwise
sayColor();

// Throws an error in strict mode, "red" otherwise
sayColor.call(null);

基本上,this -value 必須分配一個值,否則它仍然是 undefined .這意味著在沒有 new 的情況下意外調用了構造函數 也受到影響:

function Person(name) {
    this.name = name;
}

// Error in strict mode
var me = Person("Nicholas");

在這段代碼中,thisundefinedPerson 構造函數在沒有 new 的情況下被調用 .由於您無法將屬性分配給 undefined ,此代碼會引發錯誤。在非嚴格模式下,this 將被強制為全局,因此 name 將被分配為全局變量。

無重複

如果您已經進行了大量編碼,那麼在對像中複製屬性或在函數中復制命名參數可能非常容易。嚴格模式在遇到任一模式時都會引發錯誤:

// Error in strict mode - duplicate arguments
function doSomething(value1, value2, value1) {
    //code
}

// Error in strict mode - duplicate properties
var object = {
    foo: "bar",
    foo: "baz"
};

這些都是語法錯誤,所以在代碼執行之前就拋出了錯誤。

更安全的 eval()

即使 eval() 沒有被刪除,它在嚴格模式下發生了一些變化。最大的變化是在 eval() 中聲明的變量和函數 不再在包含範圍內創建語句。例如:

(function() {

    eval("var x = 10;");

    // Non-strict mode, alerts 10
    // Strict mode, throws an error because x is undeclared
    alert(x);

}());

eval() 內創建的任何變量或函數 留在 eval() 內 .但是,您可以從 eval() 返回一個值 如果你想傳回一個值:

(function() {

    var result = eval("var x = 10, y = 20; x + y");

    // Works in strict and non-strict mode (30)
    alert(result);

}());

不可變對象的錯誤

ECMAScript 5 還引入了修改屬性屬性的能力,例如將屬性設置為只讀或凍結整個對象的結構。在非嚴格模式下,嘗試修改不可變屬性會靜默失敗。您可能在使用某些原生 API 時遇到過這個問題。嚴格模式可確保每當您嘗試以不允許的方式修改對像或對象屬性時都會引發錯誤。

var person = {};
Object.defineProperty(person, "name", {
    writable: false,
    value: "Nicholas"
});

// Fails silently in non-strict mode, throws error in strict mode
person.name = "John";

在本例中,name 屬性設置為只讀。在非嚴格模式下,分配給 name 默默地失敗;在嚴格模式下,會拋出錯誤。

注意: 如果您使用任何 ECMAScript 屬性功能,我強烈建議您使用嚴格模式。如果你要改變對象的可變性,你會遇到很多錯誤,這些錯誤會在非嚴格模式下靜默失敗。

你如何使用它?

使用以下 pragma 在現代瀏覽器中很容易啟用嚴格模式:

"use strict";

儘管這看起來像一個未分配給變量的字符串,但它實際上指示符合標準的 JavaScript 引擎切換到嚴格模式(不支持嚴格模式的瀏覽器只需將其讀取為未分配的字符串並繼續照常工作) .您可以在全局範圍內或在函數內使用它。話雖如此,你不應該在全局範圍內使用它 .全局使用 pragma 意味著同一文件中的任何代碼也以嚴格模式運行。

// Don't do this
"use strict";

function doSomething() {
    // this runs in strict mode
}

function doSomethingElse() {
    // so does this
}

這可能看起來沒什麼大不了的,但是,它可能會在我們激進的腳本連接世界中引起大問題。只需要一個腳本來全局包含每個與其連接的腳本的 pragma 以切換到嚴格模式(可能會顯示您從未預料到的錯誤)。

因此,最好只在函數內部使用嚴格模式,例如:

function doSomething() {
    "use strict";
    // this runs in strict mode
}

function doSomethingElse() {
    // this doesn't run in strict mode
}

如果您希望嚴格模式應用於多個函數,請使用立即調用函數表達式 (IIFE):

(function() {

    "use strict";

    function doSomething() {
        // this runs in strict mode
    }

    function doSomethingElse() {
        // so does this
    }
}());

結論

我強烈建議大家現在就開始使用嚴格模式。有足夠多的瀏覽器支持它,嚴格模式將合法地幫助您避免錯誤,您甚至不知道代碼在哪裡。確保你沒有在全局範圍內包含 pragma,而是盡可能頻繁地使用 IIFE,將嚴格模式應用於盡可能多的代碼。最初,會出現您以前從未遇到過的錯誤——這是正常的。確保在切換到嚴格模式後進行大量測試,以確保你已經掌握了所有內容。絕對不要只拋出 "use strict" 在您的代碼中並假設沒有錯誤。最重要的是,是時候開始使用這種非常有用的語言特性來編寫更好的代碼了。

更新(2012 年 3 月 14 日): 添加了有關在不符合標準的 JavaScript 引擎中使用嚴格模式編譯指示的說明。
更新(2012 年 3 月 21 日): 修正錯字。

參考

  1. 詳細介紹 ECMA-262-5。第 2 章 Dmitry Soshnikov 的嚴格模式

Tutorial JavaScript 教程
  1. 使用 Fetch API 發送 GraphQL 查詢(沒有 Apollo,URQL)

  2. Dev.to 上的可折疊評論

  3. 在 NestJS 中管理多個環境

  4. 輕鬆創建 node-react-docker 應用

  5. 輔助項目:使用 Zomato API 的 Telegram Food Bot

  6. JavaScript 大組合問題

  7. 僅在選定的工作表上運行 onEdit 腳本

  1. 2022 年 30 個 Javascript 動畫庫

  2. 在rails中創建新模型時如何觸發一次JS代碼?

  3. p5-Svelte:在 Svelte 中使用 p5 的快速簡便的方法! 🕸🧙‍♂️

  4. 隨機顏色生成器博覽會應用程序

  5. 如何將參數傳遞給 Script 標籤?

  6. 在觸發 onChange 時僅更新列表的第一個元素

  7. CRUD APP....哪個更容易製作? REACT 或 DJANGO

  1. 介紹:Discord 的時區機器人!

  2. React 簡單的響應式菜單鉤子

  3. PostgreSQL vs MySQL:探索他們的 12 個關鍵差異

  4. IOS 表單工具欄/助手 - 幫助?!