ホームページ  >  記事  >  ウェブフロントエンド  >  javascript_javascript のヒントで厳密モードを理解する

javascript_javascript のヒントで厳密モードを理解する

WBOY
WBOYオリジナル
2016-05-16 15:16:541932ブラウズ

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

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

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

heigui = "db";

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

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

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

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

function strictFun()
{
 // 函数级别严格模式语法
 'use strict';
 console.log('I am a strictmode function!');
}

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

Chrome中調試嚴格模式
我有這麼一段程式碼:

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

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


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

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

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

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

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

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 #
非嚴格模式頂多就是值賦不上去而已,並不會報錯

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 的值为 null 或 undefined 时,该值不会转换为全局对象
比如:

"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 参数的值,从而使 oneArg 和 arguments[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. 严格模式

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

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。