JavaScript中的嚴格模式

本文同步自 個人博客,地址:http://reeoo.me/archives/strictmode.htmlhtml

什麼是嚴格模式

咱們平時寫的JavaScript代碼通常都運行在正常模式中的,除了正常運行模式,ECMAscript 5添加了第二種運行模式:"嚴格模式"(strict mode)。看名字就知道,這種模式會讓JavaScript在更嚴格的環境中運行。node

包括IE 10在內的主流瀏覽器,都已經支持它,許多大項目已經開始全面擁抱。(github上面好多項目都是用的嚴格模式)git

啓用嚴格模式

爲整個腳本啓用嚴格模式

在全部語句以前放一個特定語句 "use strict",假設有一個腳本reeoo.js,能夠這樣開啓嚴格模式:程序員

"use strict";
var name = "Reeoo";
console.log(name);

BUT這種寫法存在自然的坑,假如咱們要作代碼合併,我如今要把heigui.jsgithub

heigui = "db";

reeoo.js進行合併,原本兩個腳本分開執行是好好的,合起來就會報錯。windows

Uncaught ReferenceError: heigui is not defined(…)

一個嚴格模式的腳本和一個非嚴格模式的腳本合併可能會致使非嚴格模式的腳本代碼報錯,建議代碼都包在一個當即執行函數裏面。瀏覽器

(function(){
    "use strict";
    var name = "reeoo";
})();

(function(){
    heigui = "db";
})();

這樣合併以後就不會報錯了。閉包

爲某個函數啓用嚴格模式

要給某個函數開啓嚴格模式,得把"use strict"; 聲明放在函數體全部語句以前就好了。app

function strictFun()
{
  // 函數級別嚴格模式語法
  'use strict';
  console.log('I am a strictmode function!');
}

function normalFun() { 
    console.log('I am a mormal function!');
}

Chrome中調試嚴格模式

我有這麼一段代碼:ide

'use strict'
name = "reeoo";
console.log(name)

把這段代碼直接粘貼到Chrome的控制檯中執行,正常狀況下應該報錯,可是並無報錯,

ChromeConsole

很顯然,嚴格模式下變量不適用var聲明是不合法的,可是爲何沒有報錯?

這是什麼鬼,難道Chrome不支持嚴格模式?開什麼玩笑。。。

網上搜了一下,原來Chrome的控制檯的代碼是運行在eval之中的,你無法對eval函數使用嚴格模式(應該也不徹底對,可是具體Chrome作了什麼,不得而知),下圖說明eval函數可使用嚴格模式:

NodeEval

要想在Chrome瀏覽器中對嚴格模式正常報錯,須要在代碼外層套一個當即執行函數,或者其它相似的措施。

(function(){
    'use strict'
    name = "reeoo";
    console.log(name) 
})()

這樣就能夠了

FireFox代碼草稿紙調試嚴格模式

Chrome非要咱們包一層閉包才能跑嚴格模式,既然這麼麻煩,有沒有別的方式能夠直接跑嚴格模式的代碼呢?

FireFox有一個代碼草稿紙能夠直接跑,快捷鍵SHIFT+F4

FF代碼草稿紙

嚴格模式到底有多嚴格

嚴格模式中一些重要的限制

1. 變量聲明

不容許使用一個沒有聲明的變量

"use strict";
name = "reeoo";

報錯(代碼草稿紙,下同)

Exception: ReferenceError: assignment to undeclared variable name

2. 修改只讀屬性的值

"use strict";
var testObj = Object.defineProperties({}, {
    prop1: {
        value: 10,
        writable: false // 一個只讀的屬性
    },
    prop2: {
        get: function () {
        }
    }
});
testObj.prop1 = 20; //嘗試改變prop1的值
testObj.prop2 = 30;//嘗試改變prop2的值

嚴格模式下會報錯:

Uncaught TypeError: Cannot assign to read only property 'prop1' of #<Object>

非嚴格模式頂多就是值賦不上去而已,並不會報錯

3. 修改不可擴展的屬性

表現爲將屬性添加到 extensible 屬性設置爲 false 的對象。

"use strict";
var testObj = new Object();
Object.preventExtensions(testObj);//通過這個方法處理過的對象,不影響原有對象的刪除,修改.可是沒法添加新的屬性成員了.
testObj.name = "reeoo";

嚴格模式報錯:

Uncaught TypeError: Can't add property name, object is not extensible

非嚴格模式不會報錯,可是testObj也不會被擴展。

4. 刪除變量、函數或參數

刪除 configurable 特性設置爲 false 的屬性。

"use strict";
var testvar = 15,testObj={};
function testFunc() {};
delete testvar;
delete testFunc;

Object.defineProperty(testObj, "testvar", {
    value: 10,
    configurable: false
    });
delete testObj.testvar;

報錯:

Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.

5. 在一個對象文本中屢次定義某個屬性

嚴格模式下不容許一個屬性有多個定義

"use strict";
var testObj = {
    prop1: 10,
    prop2: 15,
    prop1: 20
};

報錯(node控制檯)

Duplicate data property in object literal not allowed in strict mode

正常模式中後聲明的重複的變量會覆蓋前面聲明的,並且不會報錯。

注:這個問題在ECMAScript6中已被修復。

6. 嚴格模式下不容許形參參數名稱重複

"use strict";
function testFunc(param1, param1) {
    return 1;
};

報錯:

Uncaught SyntaxError: Duplicate parameter name not allowed in this context

7. 沒法使用標識符的將來保留字,嚴格模式下將保留標識符名稱

一下標識符(ES6中依然沒有實現的)在嚴格模式中是不能使用的,不然也會報錯。

用了就是這個下場:

Uncaught SyntaxError: Unexpected strict mode reserved word
implements
interface
package
private
protected
public
static
yield

8. 嚴格模式下不容許使用八進制數字參數和轉義字符

"use strict";
var testoctal = 010;
var testescape = \010;

報錯:

Uncaught SyntaxError: Unexpected token ILLEGAL(…)

9. 當 this 的值爲 nullundefined 時,該值不會轉換爲全局對象

好比:

"use strict";
function testFunc() {
    return this;
}
var testvar = testFunc();

在非嚴格模式下,testvar 的值爲全局對象window,但在嚴格模式下,該值爲 undefined

10. 字符串"eval"不能用做標識符(變量或函數名、參數名等)

"use strict";
var eval = "hehe";
Uncaught SyntaxError: Unexpected eval or arguments in strict mode

11. 在嚴格模式下,函數聲明沒法嵌套在語句或塊中。它們只能顯示在頂級或直接顯示在函數體中

"use strict";
var arr = [1, 2, 3, 4, 5];
var index = null;
for (index in arr) {
    function myFunc() {};
}

node控制檯:

SyntaxError: In strict mode code, functions can only be declared at top level or immediately within another function.

可是這個限制已經在ES6中被修復。

12. 嚴格模式下eval用法無效

若是在 eval 函數內聲明變量,則不能在此函數外部使用該變量。

"use strict";
eval("var testvar = 10");
console.log(testvars);
Uncaught ReferenceError: testvar is not defined

13. 嚴格模式下"arguments"用法無效

字符串"arguments"不能用做標識符(變量或函數名、參數名等)。

"use strict";
var arguments = 1;
Uncaught SyntaxError: Unexpected eval or arguments in strict mode

這個跟上面第10條的限制是差很少的。

14. 函數內的 arguments,沒法更改arguments 對象的成員的值

"use strict";
function testArgs(oneArg) {
    arguments[0] = 20;
}

在非嚴格模式下,能夠經過更改 arguments[0] 的值來更改 oneArg 參數的值,從而使 oneArgarguments[0] 的值都爲 20。在嚴格模式下,更改 arguments[0] 的值不會影響 oneArg 的值,由於 arguments 對象只是一個本地副本。

15. 不容許使用arguments.callee

"use strict";
function my(testInt) {
    if (testInt-- == 0)
        return;
    arguments.callee(testInt--);
}
my(100);

用了的下場就是這樣:

Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

16. 不容許使用with

"use strict";
with (Math){
    x = cos(3);
    y = tan(7);
}
Uncaught SyntaxError: Strict mode code may not include a with statement

爲何要使用嚴格模式

既然這種模式這麼多限制,我爲何還要用呢?閒得蛋疼嗎?固然8是。

JavaScript做爲一門一開始用於瀏覽器的腳本語言,容錯性很是好,即便有時候你的代碼寫的不標準,也不會報錯,但這有時候會變成代碼隱患。開啓了嚴格模式以後,JavaScript的一些不合理的不嚴謹的語法都會獲得控制,讓你可以更嚴謹的書寫JavaScript代碼,成爲一個更好的程序員。嚴格模式是ES5時代的產物,ES2015已經在普及的路上,是時候使用嚴格模式了!

參考

  1. 嚴格模式

  2. 嚴格模式

相關文章
相關標籤/搜索