syntax use strict作用 - JavaScript中使用“嚴格”做什麼,背後的原因是什麼?





12 Answers

這是ECMAScript 5的一個新功能.John Resig寫了一個很好的摘要

它只是一個放在JavaScript文件中的字符串(位於文件頂部或函數內部),如下所示:

"use strict";

現在將它放在你的代碼中不應該導致當前瀏覽器出現任何問題,因為它只是一個字符串。 如果您的代碼違反了編譯指示,將來可能會導致您的代碼出現問題。 例如,如果您當前有foo = "bar"而沒有先定義foo ,那麼您的代碼將開始失敗......在我看來這是一件好事。

node js perl

最近,我通過Crockford的JSLint運行了一些我的JavaScript代碼,它給出了以下錯誤:

第1行問題1:缺少“使用嚴格”聲明。

做一些搜索,我意識到有些人加上"use strict"; 進入他們的JavaScript代碼。 一旦我添加了語句,錯誤就會停止顯示。 不幸的是,谷歌沒有透露這個字符串聲明背後的歷史。 當然它必須與瀏覽器如何解釋JavaScript有關,但我不知道效果會是什麼。

那麼什麼是"use strict"; 一切,它意味著什麼,它仍然相關嗎?

當前任何瀏覽器都會響應"use strict"; 字符串或將來使用?




如果人們擔心use strict ,可能值得查看這篇文章:

ECMAScript 5在瀏覽器中支持“嚴格模式”。 這是什麼意思?
NovoGeek.com - Krishna的博客

它討論了瀏覽器支持,但更重要的是如何安全地處理它:

function isStrictMode(){
    return !this;
} 
/*
   returns false, since 'this' refers to global object and 
   '!this' becomes false
*/

function isStrictMode(){   
    "use strict";
    return !this;
} 
/* 
   returns true, since in strict mode the keyword 'this'
   does not refer to global object, unlike traditional JS. 
   So here, 'this' is 'undefined' and '!this' becomes true.
*/



使用'use strict'; 不會突然使你的代碼變得更好。

JavaScript嚴格模式ECMAScript 5中的一項功能。 您可以通過在腳本/函數的頂部聲明這一點來啟用嚴格模式。

'use strict';

當JavaScript引擎看到此指令時 ,它將開始以特殊模式解釋代碼。 在這種模式下,當檢測到可能最終成為潛在錯誤的某些編碼實踐時(這是嚴格模式背後的原因),會引發錯誤。

考慮這個例子:

var a = 365;
var b = 030;

在他們對數字文字排列的痴迷中,開發人員無意中用八進製文字初始化了變量b 。 非嚴格模式會將其解釋為值為24的數字文字(在基數10中)。 但是,嚴格模式會拋出錯誤。

有關嚴格模式的非專業清單,請參閱此答案 。

我應該在哪裡使用'use strict';

  • 在我的 JavaScript應用程序中: 絕對! 當您使用代碼做一些愚蠢的事情時,嚴格模式可以用作舉報者。

  • 在我現有的 JavaScript代碼中: 可能不是! 如果您現有的JavaScript代碼具有嚴格模式下禁止的語句,則應用程序將會中斷。 如果您需要嚴格模式,則應準備好調試和更正現有代碼。 這就是使用'use strict'; 不會突然使你的代碼變得更好

我如何使用嚴格模式?

  1. 插入'use strict'; 在腳本之上的語句:

    // File: myscript.js
    
    'use strict';
    var a = 2;
    ....
    

    請注意,文件myscript.js中的所有內容都將以嚴格模式進行解釋。

  2. 或者,插入'use strict'; 在函數體上的語句:

    function doSomething() {
        'use strict';
        ...
    }
    

    函數doSomething詞法範圍內的所有內容都將以嚴格模式進行解釋。 詞彙範圍這個詞在這裡很重要。 請參閱此答案以獲得更好的解釋。

嚴格模式禁止哪些事情?

我找到了一篇很好的文章,描述了嚴格模式下禁止的一些事情(請注意,這不是一個獨家列表):

範圍

從歷史上看,JavaScript一直困擾著函數的作用域。 有時它們似乎是靜態範圍的,但有些功能使它們的行為類似於動態範圍。 這令人困惑,使程序難以閱讀和理解。 誤解會導致錯誤。 這也是性能問題。 靜態作用域允許在編譯時發生變量綁定,但是對動態作用域的要求意味著必須將綁定延遲到運行時,這會帶來顯著的性能損失。

嚴格模式要求所有變量綁定都是靜態完成的。 這意味著必須消除或修改以前需要動態綁定的功能。 具體來說,刪除了with語句,並且eval函數篡改其調用者環境的能力受到嚴格限制。

嚴格的代碼的好處之一是像YUI Compressor這樣的工具在處理它時可以做得更好。

隱含的全局變量

JavaScript隱含了全局變量。 如果未顯式聲明變量,則會隱式聲明全局變量。 這使得初學者的編程更容易,因為他們可以忽略一些基本的家務雜務。 但它使較大程序的管理變得更加困難,並且顯著降低了可靠性。 因此,在嚴格模式下,不再創建隱含的全局變量。 您應該明確聲明所有變量。

全球洩漏

有許多情況可能導致this綁定到全局對象。 例如,如果您在調用構造函數時忘記提供new前綴,那麼構造函數將意外地綁定到全局對象,因此它不是初始化新對象,而是靜默地篡改全局變量。 在這些情況下,嚴格模式會this綁定到undefined ,這將導致構造函數拋出異常,從而允許更快地檢測到錯誤。

吵鬧失敗

JavaScript總是具有隻讀屬性,但是在ES5的Object.createProperty函數暴露該功能之前,您無法自己創建它們。 如果您嘗試將值分配給只讀屬性,則它將以靜默方式失敗。 賦值不會改變屬性的值,但是程序會像它一樣繼續進行。 這是一種完整性危害,可能導致程序進入不一致狀態。 在嚴格模式下,嘗試更改只讀屬性將引發異常。

八進制

當在字大小為3的倍數的機器上進行機器級編程時,數字的八進制(或基數8)表示非常有用。在使用CDC 6600大型機(字大小為60位)時,需要八進制。 如果你能讀八進制,你可以看一個單詞為20位數。 兩位數表示操作碼,一位數字表示8個寄存器中的一個。 在從機器代碼到高級語言的緩慢過渡期間,認為在編程語言中提供八進制形式是有用的。

在C中,選擇了非常不幸的八進製表示:前導零。 因此在C中, 0100表示64,而不是100,而08是錯誤,而不是8.更不幸的是,這種時代錯誤被複製到幾乎所有現代語言中,包括JavaScript,它只用於創建錯誤。 它沒有其他目的。 因此在嚴格模式下,不再允許八進制形式。

等等

參數偽數組在ES5中變得更像陣列。 在嚴格模式下,它會丟失其calleecaller屬性。 這使得可以將arguments傳遞給不受信任的代碼,而不會放棄大量的機密上下文。 此外,消除了函數的arguments屬性。

在嚴格模式下,函數文字中的重複鍵將產生語法錯誤。 函數不能有兩個具有相同名稱的參數。 函數不能具有與其參數之一具有相同名稱的變量。 函數無法delete自己的變量。 嘗試delete不可配置的屬性現在會拋出異常。 原始值不是隱式包裝的。

未來JavaScript版本的保留字

ECMAScript 5添加了一個保留字列表。 如果將它們用作變量或參數,則嚴格模式將引發錯誤。 保留字是:

implementsinterfaceletpackageprivateprotectedpublicstaticyield

進一步閱讀




我想提供一個更有根據的答案,補充其他答案。 我希望編輯最流行的答案,但失敗了。 我試圖讓它盡可能全面和完整。

您可以參考MDN文檔以獲取更多信息。

"use strict" ECMAScript 5中引入的指令。

指令與陳述類似,但不同。

  • use strict不包含關鍵字:該指令是一個簡單的表達式語句,它由一個特殊的字符串文字(單引號或雙引號)組成。 沒有實現ECMAScript 5的JavaScript引擎只能看到沒有副作用的表達式語句。 預計未來版本的ECMAScript標準會將其用作真正的關鍵詞; 因此報價將變得過時。
  • use strict只能在腳本或函數的開頭使用,即它必須在每個其他(真實)語句之前。 它不必是函數腳本中的第一條指令:它可以在其他由字符串文字組成的語句表達式之前(並且JavaScript實現可以將它們視為特定於實現的指令)。 字符串文字語句遵循第一個真實語句(在腳本或函數中)是簡單的表達式語句。 口譯員不得將其解釋為指令,也不得影響。

use strict指令表明以下代碼(在腳本或函數中)是嚴格的代碼。 當腳本包含use strict指令時,腳本最高級別的代碼(不在函數中的代碼)被視為嚴格代碼。 當函數本身在嚴格代碼中定義或函數包含use strict指令時,函數的內容被視為嚴格代碼。 當從嚴格代碼調用eval()或包含use strict指令本身時,傳遞給eval()方法的代碼被視為嚴格代碼。

ECMAScript 5的嚴格模式是JavaScript語言的有限子集,它消除了語言的相關缺陷,並具有更嚴格的錯誤檢查和更高的安全性。 以下列出了嚴格模式和普通模式之間的區別(前三個特別重要):

  • 您不能在嚴格模式下使用with -statement。
  • 在嚴格模式下,必須聲明所有變量:如果為尚未聲明為變量,函數,函數參數,catch-clause參數或全局Object屬性的標識符賦值,則會得到ReferenceError 。 在正常模式下,標識符被隱式聲明為全局變量(作為全局Object的屬性)
  • 在嚴格模式下,關鍵字this在作為函數(而不是方法)調用的函數中具有undefined的值。 (在正常模式下, this始終指向全局Object )。 這種差異可用於測試實現是否支持嚴格模式:
var hasStrictMode = (function() { "use strict"; return this===undefined }());
  • 此外,當使用call()調用函數或在嚴格模式下apply時, this正是call()apply()調用的第一個參數的值。 (在正常模式下, nullundefined將被全局Object替換,而非對象的值將被轉換為對象。)

  • 在嚴格模式下,當您嘗試分配給只讀屬性或為非可擴展對象定義新屬性時,您將獲得TypeError 。 (在正常模式下,兩者都會失敗而沒有錯誤消息。)

  • 在嚴格模式下,當將代碼傳遞給eval() ,您無法在調用者的範圍內聲明或定義變量或函數(正如您在普通模式下所做的那樣)。 而是為eval()創建一個新範圍,變量和函數在該範圍內。 eval()完成執行後,該範圍被銷毀。
  • 在嚴格模式下,函數的arguments-object包含值的靜態副本,這些副本將傳遞給該函數。 在正常模式下,arguments-object有一些“神奇”的行為:數組的元素和命名的函數參數都引用相同的值。
  • 在嚴格模式下,當delete運算符後跟非限定標識符(變量,函數或函數參數)時,將獲得SyntaxError 。 在正常模式下, delete表達式將不執行任何操作,並將其計算為false
  • 在嚴格模式下,當您嘗試刪除不可配置的屬性時,將獲得TypeError 。 (在正常模式下,嘗試只是失敗, delete表達式被評估為false )。
  • 在嚴格模式下,當您嘗試為對象文字定義具有相同名稱的多個屬性時,會將其視為語法錯誤。 (在正常模式下沒有錯誤。)
  • 在嚴格模式下,當函數聲明具有多個具有相同名稱的參數時,它被認為是語法錯誤。 (在正常模式下沒有錯誤。)
  • 在嚴格模式下,不允許八進製文字(這些是以0x文字。(在正常模式下,某些實現允許八進製文字。)
  • 在嚴格模式下,標識符evalarguments被視為關鍵字。 您不能更改它們的值,不能為它們賦值,也不能將它們用作變量,函數,函數參數或catch塊標識符的名稱。
  • 在嚴格模式下,對檢查調用堆棧的可能性有更多限制。 arguments.callerarguments.callee在嚴格模式下導致函數中的TypeError 。 此外,嚴格模式下函數的某些調用者和參數屬性在您嘗試讀取時會導致TypeError



如果您使用過去一年左右發布的瀏覽器,那麼它很可能支持JavaScript Strict模式。 只有在ECMAScript 5成為當前標準之前的舊瀏覽器才支持它。

命令周圍的引號確保代碼仍然可以在舊版瀏覽器中工作(儘管在嚴格模式下生成語法錯誤的事情通常只會導致腳本在這些舊版瀏覽器中以某種難以檢測的方式出現故障)。




添加"use strict"; ,以下情況將在腳本執行之前拋出一個SyntaxError

  • 為未來的ECMAScript版本舖平道路 ,使用一個新保留的關鍵字(在ECMAScript 6預設中 ): implementsinterfaceletpackageprivateprotectedpublicstaticyield

  • 在塊中聲明函數

    if(a<b){ function f(){} }
    
  • 八進制語法

    var n = 023;
    
  • this一點指向全局對象。

     function f() {
          "use strict";
          this.a = 1;
     };
     f(); 
    
  • 為對象文字中的屬性名稱聲明兩次相同的名稱

     {a: 1, b: 3, a: 7} 
    

    在ECMAScript 6中不再是這種情況( 錯誤1041128 )。

  • 使用相同的名稱函數聲明兩個函數參數

    f(a, b, b){}
    
  • 將值設置為未聲明的變量

    function f(x){
       "use strict";
       var a = 12;
       b = a + x*35; // error!
    }
    f();
    
  • 使用delete變量名稱delete myVariable;

  • 使用evalarguments作為變量或函數參數名稱

    "use strict";
    arguments++;
    var obj = { set p(arguments) { } };
    try { } catch (arguments) { }
    function arguments() { } 
    

資料來源:




use strict從這一點開始包括所有敏感JavaScript文件的開頭是一個很好的方法,可以成為一個更好的JavaScript程序員,並避免隨機變量變為全局變量,事情會無聲地改變。




一些參與ECMAScript委員會的人員進行了很好的討論:JavaScript的變化,第1部分:ECMAScript 5“關於"use strict"交換機的增量使用如何允許JavaScript實施者清理JavaScript的許多危險特性而不會突然破壞每個網站在世界上。

當然,它還討論了很多這些錯誤的內容以及ECMAScript 5如何修復它們。




請注意,這use strict是在EcmaScript 5中引入的,並且從那時開始保留。

以下是在ES6ES7觸發嚴格模式的條件:

  • 全局代碼是嚴格模式代碼,如果它以包含使用嚴格指令的指令序言開頭(見14.1.1)。
  • 模塊代碼始終是嚴格的模式代碼。
  • ClassDeclarationClassExpression的所有部分都是嚴格模式代碼。
  • 如果Eval代碼以包含Use Strict Directive的Directive Prologue開頭,或者對eval的調用是嚴格模式代碼中包含的直接eval(見12.3.4.1),則Eval代碼是嚴格模式代碼。
  • 如果關聯的FunctionDeclaration,FunctionExpression,GeneratorDeclaration,GeneratorExpression,MethodDefinition或ArrowFunction包含在嚴格模式代碼中,或者產生函數[[ECMAScriptCode]]內部槽的值的代碼以指令序言開頭,則函數代碼是嚴格模式代碼包含使用嚴格指令。
  • 作為內置函數和生成器構造函數的參數提供的函數代碼是嚴格模式代碼,如果最後一個參數是一個String,處理時是一個以包含Use Strict指令的Directive Prologue開頭的FunctionBody



開發人員應該使用的主要原因"use strict"是:

  1. 防止意外聲明全局變量。"use strict()"使用var前將確保變量在使用前聲明。例如:

    function useStrictDemo(){
     'use strict';
     //works fine
     var a = 'No Problem';
    
     //does not work fine and throws error
     k = "problem"
    
     //even this will throw error
     someObject = {'problem': 'lot of problem'};
    }
    
  2. 注意:該"use strict"指令僅在腳本或函數的開頭被識別。
  3. 該字符串"arguments"不能用作變量:

    "use strict";
    var arguments = 3.14;    // This will cause an error
    
  4. 將限制使用關鍵字作為變量。試圖使用它們會引發錯誤。

簡而言之,這將使您的代碼不易出錯,反過來會讓您編寫好的代碼。

要了解更多信息,請參閱此處




“嚴格使用”; 是ECMA努力使JavaScript更加強大。它引入了JS,試圖使其至少有一點“嚴格”(其他語言自90年代起實施嚴格的規則)。它實際上“迫使”JavaScript開發人員遵循某種編碼最佳實踐。JavaScript仍然非常脆弱。沒有類型變量,類型化方法等。我強烈建議JavaScript開發人員學習更強大的語言,如Java或ActionScript3,並在JavaScript代碼中實現相同的最佳實踐,它會更好地工作,更容易調試。




通常,java腳本不遵循嚴格的規則,因此增加了錯誤的可能性。使用之後"use strict",java腳本代碼應該遵循嚴格的規則集,就像在其他編程語言中一樣,例如使用終結符,初始化之前的聲明等。

如果"use strict"使用,則應遵循嚴格的規則集編寫代碼,從而減少錯誤和模糊的可能性。




Related