1. 程式人生 > >javaScript 嚴格模式

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.瀏覽器的嚴格模式

主流瀏覽器都已經支援嚴格模式,但是有大量瀏覽器版本部分支援或者是根本不支援嚴格模式。

4. 其他