Strict mode
ECMAScript 5 提供開發者語法嚴格、語法受限的模式 (strict mode) ,會影響語法的使用但沒支援受限模式的瀏覽器一樣可以跑,只是行為有很大的可能會跟你想的不一樣。所以別太依賴受限模式,除非你做過功能性測試。另外這個模式可以混用在普通模式裡,你可以利用這個特性慢慢把舊的程式碼轉變成完全嚴謹和低變化性的狀態。
這個模式裡做了些語意上的修正:
- 透過拋出錯誤的方式消除一些安靜的錯誤(意指不再靜默地忽略某些錯誤)
- 修正會阻礙 JavaScript 引擎進行最佳化的錯誤: 相同的程式碼在嚴格模式有時候能運行得比非嚴格模式來的快
- 禁止使用一些有可能被未來版本 ECMAScript 定義的語法
參考 過渡到嚴格模式,如果你希望將你的程式碼在 JavaScript 語法嚴格、語法受限下執行。
備註:Sometimes, you'll see the default, non-strict, mode referred to as "sloppy mode". This isn't an official term, but be aware of it, just in case.
用法
嚴格模式可以用於整份腳本或個別函數中。不要在封閉的大括弧內 {} 這樣做; 這麼做在上下文中是沒有效果的。eval 程式、Function、事件處理參數、傳入 WindowTimers.setTimeout() 函數的字串都是整個腳本,開啟嚴格模式他也會如預期般運作。
Strict mode for scripts
To invoke strict mode for an entire script, put the exact statement "use strict"; (or 'use strict';) before any other statements.
// Whole-script strict mode syntax
"use strict";
var v = "Hi! I'm a strict mode script!";
This syntax has a trap that has already bitten a major site: it isn't possible to blindly concatenate non-conflicting scripts. Consider concatenating a strict mode script with a non-strict mode script: the entire concatenation looks strict! The inverse is also true: non-strict plus strict looks non-strict. Concatenation of strict mode scripts with each other is fine, and concatenation of non-strict mode scripts is fine. Only concatenating strict and non-strict scripts is problematic. It is thus recommended that you enable strict mode on a function-by-function basis (at least during the transition period).
You can also take the approach of wrapping the entire contents of a script in a function and having that outer function use strict mode. This eliminates the concatenation problem but it means that you have to explicitly export any global variables out of the function scope.
Strict mode for functions
Likewise, to invoke strict mode for a function, put the exact statement "use strict"; (or 'use strict';) in the function's body before any other statements.
function strict() {
// Function-level strict mode syntax
"use strict";
function nested() {
return "And so am I!";
}
return "Hi! I'm a strict mode function! " + nested();
}
function notStrict() {
return "I'm not strict.";
}
Changes in strict mode
Strict mode changes both syntax and runtime behavior. Changes generally fall into these categories: changes converting mistakes into errors (as syntax errors or at runtime), changes simplifying how the particular variable for a given use of a name is computed, changes simplifying eval and arguments, changes making it easier to write "secure" JavaScript, and changes anticipating future ECMAScript evolution.
Converting mistakes into errors
Strict mode changes some previously-accepted mistakes into errors. JavaScript was designed to be easy for novice developers, and sometimes it gives operations which should be errors non-error semantics. Sometimes this fixes the immediate problem, but sometimes this creates worse problems in the future. Strict mode treats these mistakes as errors so that they're discovered and promptly fixed.
First, strict mode makes it impossible to accidentally create global variables. In normal JavaScript mistyping a variable in an assignment creates a new property on the global object and continues to "work" (although future failure is possible: likely, in modern JavaScript). Assignments which would accidentally create global variables instead throw in strict mode:
"use strict";
// Assuming a global variable mistypedVariable exists
mistypeVariable = 17; // this line throws a ReferenceError due to the
// misspelling of variable
Second, strict mode makes assignments which would otherwise silently fail to throw an exception. For example, NaN is a non-writable global variable. In normal code assigning to NaN does nothing; the developer receives no failure feedback. In strict mode assigning to NaN throws an exception. Any assignment that silently fails in normal code (assignment to a non-writable global or property, assignment to a getter-only property, assignment to a new property on a non-extensible object) will throw in strict mode:
"use strict";
// Assignment to a non-writable global
var undefined = 5; // throws a TypeError
var Infinity = 5; // throws a TypeError
// Assignment to a non-writable property
var obj1 = {};
Object.defineProperty(obj1, "x", { value: 42, writable: false });
obj1.x = 9; // throws a TypeError
// Assignment to a getter-only property
var obj2 = {
get x() {
return 17;
},
};
obj2.x = 5; // throws a TypeError
// Assignment to a new property on a non-extensible object
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = "ohai"; // throws a TypeError
Third, strict mode makes attempts to delete undeletable properties throw (where before the attempt would simply have no effect):