1、介紹嚴格模式
2、嚴格模式影響范圍
- 變量: var、delete、變量關鍵字
- 對象: 只讀屬性、 對象字面量屬性重復申明
- 函數:參數重名、arguments對象、申明
- 其他:this、eval、關鍵字...
嚴格模式
ECMAScript 5 引入嚴格模式('strict mode')概念。通過嚴格模式,在函數內部選擇進行較為嚴格的全局或局部的錯誤條件檢測,使用嚴格模式的好處是可以提早知道代碼中的存在的錯誤,
及時捕獲一些可能導致編程錯誤的ECMAScript行為。在開發中使用嚴格模式能幫助我們早發現錯誤。
設立"嚴格模式"的目的,主要有以下幾個:錯誤檢測、規范、效率、安全、面向未來
- 消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為;
- 消除代碼運行的一些不安全之處,保證代碼運行的安全;
- 提高編譯器效率,增加運行速度;
- 為未來新版本的Javascript做好鋪墊。
進入"嚴格模式"的編譯指示(pragma),是下面這行語句:
"use strict";
這個語法從ECMAScript 3 開始支持。向后兼容不支持嚴格模式的瀏覽器,他們就當遇到了一個普通字符串,編譯時忽略。
將"use strict"放在腳本文件的第一行,則整個腳本都將以"嚴格模式"運行。
如果這行語句不在第一行,則無效,整個腳本以"正常模式"運行。
如果不同模式的代碼文件合並成一個文件,這一點需要特別注意。
(嚴格地說,只要前面不是產生實際運行結果的語句,"use strict"可以不在第一行,比如直接跟在一個空的分號后面。)
<script> "use strict"; console.log("這是嚴格模式。"); </script> <script> console.log("這是正常模式。"); </script>
將"use strict"放在函數體的第一行,則整個函數以"嚴格模式"運行。
function strict(){ "use strict"; return "這是嚴格模式。"; } function notStrict() { return "這是正常模式。"; }
建議只在特定的作用域中使用嚴格模式。放在全局作用域中(函數外部),頁面的其他腳本也都處於嚴格模式下。因為上面的調用方法不利於文件合並,所以更好的做法是,下面的方法,將整個腳本文件放在一個立即執行的函數表達式IIFE之中。
+function (){ "use strict"; }();
變量
非嚴格模式下,a = 1可以創建一個全局變量。
嚴格模式下,變量都必須先用var命令顯示聲明,然后再使用。 嚴格模式不允許意外創建的全局變量(示例),否則會報錯(Uncaught ReferenceError: v is not defined )。
"use strict"; v = 1; // 報錯,v未聲明 for(i = 0; i < 2; i++) { // 報錯,i未聲明 ReferenceError }
而且,嚴格模式不能對變量調用 delete 操作符(示例),會導致錯誤(Uncaught SyntaxError: Delete of an unqualified identifier in strict mode. )。
非嚴格模式允許這樣操作,但返回false 。
別用這些詞做 變量名 或 參數名 implements, interface, let, package, private, protected, public, static, yield。
這些都是保留字,將來ECMAScript 版本中可能會用到他們。
嚴格模式下作為其保留關鍵字,使用這些標識符作為變量名會導致語法錯誤。
function package(protected){ // 報錯! "use strict"; var implements; // 報錯! interface: // 報錯! while (true){ break interface; // 報錯! } function private() { } // 報錯! } function fun(static) { 'use strict'; } // 報錯!
對象
為只讀屬性賦值報錯(示例)
"use strict" var testObj = Object.defineProperties({}, { prop1: { value: 10, writable: false // by default }, prop2: { get: function () { } }
對象字面量同一個屬性重復賦值(Uncaught SyntaxError: Unexpected identifier),非嚴格模式會取最后一個(示例)
"use strict" var person = { name : "Tom" name : "Cat" }
另外兩種情況:
為不可配置的屬性使用delete操作符會拋出typeError
為不可擴展的對象添加屬性會拋出TypeError
函數
嚴格模式下參數名不能重復(Uncaught SyntaxError: Strict mode function may not have duplicate parameter names)(示例)
非嚴格模式,函數內部實際訪問的是第二個參數,要訪問第一個參數必須通過arguments對象
"use strict"
function sum(num, num) {}
非嚴格模式下,修改命名參數值也會反映到arguments對象中,
嚴格模式下者兩個值是完全獨立的。(示例)
"use strict" function showValue(value) { value = "Foo" alert(value) // Foo alert(arguments[0]) // 嚴格模式 hi // 非嚴格模式 Foo } showValue("hi")
不允許非頂層的函數。也就是,只能在腳本的頂級和在函數內部申明函數,if for等語句中申明函數會導致語法錯誤。
"use strict"; if (true){ function f() { } // 報錯! syntax error f(); } for (var i = 0; i < 5; i++){ function f2() { } // 報錯! syntax error f2(); } function baz(){ // kosher function eit() { } // also kosher }
this
嚴格模式下抑制this
(function(){ return this; })() Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…} (function(){ 'use strict'; return this; })() undefined
其他
去掉了with。
數字前面別加0。因為...禁用八進制算法。因為八進制不包含在ECMAScript中,數字前面的0會改變數字的含義,js會認為是一個八進制數,從而報錯。
"use strict"; var sum = 015 + // 報錯! syntax error 197 + 142;
還有其他例子
參考資料:
http://msdn.microsoft.com/zh-cn/library/br230269(v=vs.94).aspx