javaScript 嚴格模式
1. “use strict” 開啟嚴格模式
(1)給script標籤開啟嚴格模式
(2)給function開啟嚴格模式function() {“use strict”; }
2. 嚴格模式的不同之處
(1)將拼寫錯誤轉換成異常
a. 無法再意外得建立全域性變數
"use strict";
var hei;
hie = 1;
Uncaught ReferenceError: hie is not defined
b. 靜默失敗的賦值丟擲異常
靜默失敗(silently fall):不報錯也沒有任何效果。給不可寫屬性賦值,給只讀屬性賦值,給不可擴充套件物件的新屬性賦值,這些情況都可以引起靜默失敗。
"use strict";
var fixed = {};
Object.preventExtensions(fixed);
fixed.addProp = "hi";
Uncaught TypeError: Cannot add property newProp, object is not extensible
c. 試圖刪除不可刪除的屬性時會丟擲異常
"use strict";
delete Object.prototype;
Uncaught TypeError: Cannot delete property ‘prototype’ of function Object() { [native code] }
d. 在Gecko版本34之前,要求一個物件內的所有屬性名在物件內是唯一的,現在已經沒有這個bug了。
"use strict";
var obj = {p: 1, p: 2};
e. 要求函式的引數名唯一
非嚴格模式,同名的引數後者會覆蓋前者,但是前者還是可以通過 arguments[i] 來訪問。在嚴格模式中,有語法錯誤
function sum (a, a, c) {
"use strict";
return a + b + c;
}
Uncaught SyntaxError: Duplicate parameter name not allowed in this context
f. 禁止八進位制數字語法
瀏覽器支援八進位制語法;
var a = 010;
console.log(a); // a = 8;
ES6支援為一個數字加“0”的字首表示八進位制。但是有些開發者會省略掉”0”,這樣可能會導致錯誤,所以嚴格模式是禁止八進位制的。會丟擲語法錯誤。
"use strict";
var a = 010;
Uncaught SyntaxError: Octal literals are not allowed in strict mode.
g. 禁止設定primitive值的屬性
不採用嚴格模式,設定屬性的操作會被忽略;採用嚴格模式,將丟擲TypeError錯誤。
primitive(原始)值或primitive資料型別不是一個物件,沒有methods。在JavaScript中,有6種primitive資料型別: string,number, boolean, null, undefined, symbol(ES6)
"use strict";
false.true = '';
Uncaught TypeError: Cannot create property ‘true’ on boolean ‘false’
(2). 簡化變數的使用
簡化了程式碼中變數名稱對映到變數定義的方式。有利於編譯器的優化。
a. 禁止使用with。
with用於設定特定物件的作用域,也就是with塊裡面的所有變數都是優先在傳入的物件屬性中查詢,找不到再找作用域之外的。
var a = 123;
var b = {a: 321};
with (b) {
console.log(a); // 321
}
var d = {};
with (d) {
console.log(a);// 123
}
with引起的問題是塊內的任何名稱可以對映到with傳進來的物件的屬性,也可以對映到包圍這個塊的作用域內的變數,甚至是全域性變數,這一切都是在執行時決定的。為了優化,所以禁用了with。
"use strict";
var x = 1;
var obj = {x: 2};
with (obj) {
console.log(x);
}
Uncaught SyntaxError: Strict mode code may not include a with statement
一種替代with 的方法是,將目標物件賦值給一個短命名變數,然後訪問變數上的相應屬性。
b. 嚴格模式下,eval 不再為上層範圍(surrounding scope,也就是包圍eval程式碼塊的範圍)引入新變數。
eval(string),計算某個字串,並且執行其中的JavaScript程式碼。
c. 嚴格模式禁止刪除宣告變數。
非嚴格模式
var a = 1;
delete a;
console.log(a); // a = 1
嚴格模式
"use strict";
var a = 1;
delete a;
Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
(3). 讓eval 和arguments 變得簡單
a. 名稱eval 和 arguments 不能通過程式語法被繫結或者是賦值。
"use strict";
eval = 17;
arguments ++;
Uncaught SyntaxError: Unexpected eval or arguments in strict mode
b. 嚴格模式下,引數的值不會隨arguments 物件的值改變而改變。
非嚴格模式下
function f(a) {
a = 42;
return [a, arguments[0]];
}
var pair = f(17);
console.log(pair[0]); // 42
console.log(pair[1]);// 42
嚴格模式下
function f(a) {
"use strict";
a = 42;
return [a, arguments[0]];
}
var pair = f(17);
console.log(pair[0]); // 42
console.log(pair[1]);// 17
c. 不再支援arguments.callee。
非嚴格模式下,arguments.callee指向當前正在執行的函式。
嚴格模式下:
"use strict";
function f() {
return arguments.callee;
}
Uncaught TypeError: ‘caller’, ‘callee’, and ‘arguments’ properties may not be accessed on strict mode functions or the arguments objects for calls to them
(4). 安全的JavaScript
a. 嚴格模式下通過this傳遞給一個函式的值,不會被強制性轉換為一個物件。如果沒有指定this,它的值是undefined。
非嚴格模式
function fun() {return this;}
console.log(fun()); // Window
console.log(fun().call(2)); // Number
console.log(fun().apply(null)); // Window
console.log(fun().call(undefined)); // Window
console.log(fun().bind(true)); // Boolean
嚴格模式
"use strict";
function fun() {return this;}
console.log(fun()); // undefined
console.log(fun().call(2)); // 2
console.log(fun().apply(null)); // null
console.log(fun().call(undefined)); // undefined
console.log(fun().bind(true)); // true
b. 嚴格模式下再也不能通過廣泛實現的ECMAScript遊走於JavaScript棧中。
比如,一個函式fun 它的 fun.caller(返回最後一個呼叫fun的函式),fun.arguments都是不可刪除的屬性,而且在取值和存值的時候會報錯。
非嚴格模式下:
function b() {
console.log(b.caller);
console.log(b.arguments);
}
function a() {
b();
}
a();
嚴格模式下:
Uncaught TypeError: ‘caller’ and ‘arguments’ are restricted function properties and cannot be accessed in this context.
c. 嚴格模式下arguments不會再提供訪問與呼叫這個函式相關變數的途徑。
arguments.caller物件,儲存的屬性指向那個函式的變數。arguments.caller是不可刪除的屬性,而且在取值和存值的時候會報錯。
非嚴格模式下:
function fun(a, b) {
var v = 2;
return arguments.caller;
}
console.log(fun(1, 2)); // undefined
嚴格模式:
自己嘗試的結果跟非嚴格模式一樣,跟文件中不一樣,為啥?
(5). 為未來的ECMAScript版本鋪平道路
a. 以下保留字在嚴格模式下將不能作為變數名或者是形參。
implements, interface, let, package, private, protected, public, static, yield
b. 嚴格模式禁止了不在指令碼或者是函式層面上的函式宣告。
非嚴格模式下,在哪兒都是可以宣告函式的。例如:
var flag = true;
if (flag) {
function change() {
flag = false;
}
change();
}
在嚴格模式下,是不建議這麼做的。
3.瀏覽器的嚴格模式
主流瀏覽器都已經支援嚴格模式,但是有大量瀏覽器版本部分支援或者是根本不支援嚴格模式。