理解javascript中的strict 模式_javascript技巧

來源:互聯網
上載者:User

一、什麼是strict 模式
我們平時寫的JavaScript代碼一般都運行在正常模式中的,除了正常運行模式,ECMAscript 5添加了第二種運行模式:”strict 模式”(strict mode)。看名字就知道,這種模式會讓JavaScript在更嚴格的環境中運行。
包括IE 10在內的主流瀏覽器,都已經支援它,許多大項目已經開始全面擁抱。(github上面好多項目都是用的strict 模式)
二、啟用strict 模式
為整個指令碼啟用strict 模式
在所有語句之前放一個特定語句 "use strict";
假設有一個指令碼reeoo.js,可以這樣開啟strict 模式:

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

BUT這種寫法存在天然的坑,假如我們要做代碼合并,我現在要把heigui.js:

heigui = "db";

和reeoo.js進行合并,本來兩個指令碼分開執行是好好的,合起來就會報錯。
Uncaught ReferenceError: heigui is not defined(…)
一個strict 模式的指令碼和一個非strict 模式的指令碼合并可能會導致非strict 模式的指令碼代碼報錯,建議代碼都包在一個立即執行函數裡面。

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

這樣合并之後就不會報錯了。
為某個函數啟用strict 模式
要給某個函數開啟strict 模式,得把"use strict"; 聲明放在函數體所有語句之前就行了。

function strictFun(){ // 函數層級strict 模式文法 'use strict'; console.log('I am a strictmode function!');}function normalFun() {  console.log('I am a mormal function!');}

Chrome中調試strict 模式
我有這麼一段代碼:

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

把這段代碼直接粘貼到Chrome的控制台中執行,正常情況下應該報錯,但是並沒有報錯,


很顯然,strict 模式下變數不適用var聲明是不合法的,但是為什麼沒有報錯?
這是什麼鬼,難道Chrome不支援strict 模式?開什麼玩笑。。。
網上搜了一下,原來Chrome的控制台的代碼是運行在eval之中的,你沒法對eval函數使用strict 模式(應該也不完全對,但是具體Chrome做了什麼,不得而知),下圖說明eval函數可以使用strict 模式:

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

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

這樣就可以了
FireFox代碼草稿紙調試strict 模式
Chrome非要我們包一層閉包才能跑strict 模式,既然這麼麻煩,有沒有別的方式可以直接跑strict 模式的代碼呢?
FireFox有一個代碼草稿紙可以直接跑,快速鍵SHIFT+F4

strict 模式到底有多嚴格
strict 模式中一些重要的限制

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的值

strict 模式下會報錯:
Uncaught TypeError: Cannot assign to read only property 'prop1' of #<Object>
非strict 模式頂多就是值賦不上去而已,並不會報錯

3、修改不可擴充的屬性
表現為將屬性添加到 extensible 屬性設定為 false 的對象。

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

strict 模式報錯:
Uncaught TypeError: Can't add property name, object is not extensible
非strict 模式不會報錯,但是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、在一個對象文本中多次定義某個屬性
strict 模式下不允許一個屬性有多個定義

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

報錯(node控制台)
Duplicate data property in object literal not allowed in strict mode
正常模式中後聲明的重複的變數會覆蓋前面聲明的,而且不會報錯。
註:這個問題在ECMAScript6中已被修複。

6、strict 模式下不允許形參參數名稱重複

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

報錯:
Uncaught SyntaxError: Duplicate parameter name not allowed in this context

7、無法使用標識符的未來保留字。strict 模式下將保留標識符名稱
一下標識符(ES6中依然沒有實現的)在strict 模式中是不能使用的,否則也會報錯。
用了就是這個下場:
Uncaught SyntaxError: Unexpected strict mode reserved word

  • implements
  • interface
  • package
  • private
  • protected
  • public
  • static
  • yield

8、strict 模式下不允許使用八位元字參數和逸出字元

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

報錯:
Uncaught SyntaxError: Unexpected token ILLEGAL(…)
9、當this 的值為 null 或 undefined 時,該值不會轉換為全域對象
比如:

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

在非strict 模式下,testvar 的值為全域對象window,但在strict 模式下,該值為 undefined。

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

"use strict";var eval = "hehe";

Uncaught SyntaxError: Unexpected eval or arguments in strict mode

11、在strict 模式下,函式宣告無法嵌套在語句或塊中。它們只能顯示在頂級或直接顯示在函數體中

"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、strict 模式下eval用法無效
如果在 eval 函數內聲明變數,則不能在此函數外部使用該變數。

"use strict";eval("var testvar = 10");console.log(testvars);

Uncaught ReferenceError: testvar is not defined

13、strict 模式下"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;}

在非strict 模式下,可以通過更改 arguments[0] 的值來更改 oneArg 參數的值,從而使 oneArg 和 arguments[0] 的值都為 20。在strict 模式下,更改 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
為什麼要使用strict 模式
既然這種模式這麼多限制,我為什麼還要用呢?閑得蛋疼嗎?當然8是,
JavaScript作為一門一開始用於瀏覽器的指令碼語言,容錯性非常好,即使有時候你的代碼寫的不標準,也不會報錯,但這有時候會變成代碼隱患。開啟了strict 模式之後,JavaScript的一些不合理的不嚴謹的文法都會得到控制,讓你能夠更嚴謹的書寫JavaScript代碼,成為一個更好的程式員。strict 模式是ES5時代的產物,ES2015已經在普及的路上,是時候使用strict 模式了!

參考
  1. strict 模式
  2. strict 模式

原文:http://reeoo.me/archives/strictmode.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.