Strict Mode (JavaScript)
摘要:
ECMAScript5中引入的严格模式,通过让JavaScript运行环境对一些开发过程中最常见和不易发现的错误做出和当前不同的处理,来让开发者拥有一个”更好”的JavaScript语言。但目前为止,所有主流的浏览器都在他们的高版本中支持了严格模式,包括IE10、Firefox4、chrome12、Opera12、Android4和IOS5。
严格模式是一个更好的方法引入检查错误代码。使用严格的模式时,您不能,例如,使用隐式声明变量,给只读属性赋值,或将属性添加到一个不可扩展的对象中。
声明严格模式:
你可以宣布严格模式通过添加“use strict”;在一个文件、一个程序或一个函数的开始。这种声明称为指令序言。严格模式声明的范围取决于它的上下文。如果它是宣布在全局上下文(一个函数的范围之外),程序的所有代码在严格的模式下执行。如果在一个函数内声明它,则函数内所有的代码在严格模式下执行。例如,在下面的示例中所有的代码都是在严格模式下,函数外声明的变量导致语法错误“变量未定义的严格模式”。
1 "use strict"; 2 function testFunction(){ 3 var testvar = 4; 4 return testvar; 5 } 6 // This causes a syntax error. 7 testvar = 5;
在接下来的例子中,只有testFunction里面的代码在严格模式下执行。函数外的变量未声明不会导致一个语法错误,但在函数内会导致语法错误。
1 function testFunction(){ 2 "use strict"; 3 // This causes a syntax error. 4 testvar = 4; 5 return testvar; 6 } 7 testvar = 5;
注意:
- 如果浏览器不支持严格模式会忽略"use strict"这个字符串。这样就允许跨浏览器的使用严格模式语法,这是为了保证向前兼容,防止有一天某些浏览器仅仅支持严格模式。测试你的浏览器是否支持严格模式
- 当严格模式的方法调用了一个非严格方法时,该非严格方法不会启用严格模式,因为非严格方法被当作参数传递或是通过call和apply调用
- 当严格模式的方法调用了一个非严格方法时,该非严格方法不会启用严格模式,因为非严格方法被当作参数传递或是通过call和apply调用
严格模式的利与弊:
- 优点:
提高编译器效率,增加运行速度
消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为
消除代码运行的一些不安全之处,保证代码运行的安全 - 缺点:
在"严格模式"中,同样的代码可能会有不一样的运行结果
一些在"正常模式"下可以运行的语句,在"严格模式"下将不能运行
严格模式的限制:
下表列出了在严格模式最重要的限制
Language element |
Restriction |
Error |
Example |
Variable |
Using a variable without declaring it. |
SCRIPT5042: Variable undefined in strict mode |
testvar = 4; |
Read-only property |
Writing to a read-only property. |
SCRIPT5045: Assignment to read-only properties is not allowed in strict mode |
var testObj = Object.defineProperties({}, { prop1: { value: 10, writable: false // by default }, prop2: { get: function () { } } }); testObj.prop1 = 20; testObj.prop2 = 30; |
Non-extensible property |
Adding a property to an object whoseextensibleattribute is set to false. |
SCRIPT5046: Cannot create property for a non-extensible object |
var testObj = new Object(); Object.preventExtensions(testObj); testObj.name = "Bob"; |
delete |
Deleting a variable, a function, or an argument. Deleting a property whoseconfigurableattribute is set to false. |
SCRIPT1045: Calling delete on <expression>is not allowed in strict mode |
var testvar = 15;function testFunc() {};delete testvar;delete testFunc; Object.defineProperty(testObj, "testvar", { value: 10, configurable: false });delete testObj.testvar; |
Duplicating a property |
Defining a property more than once in an object literal. |
SCRIPT1046: Multiple definitions of a property not allowed in strict mode |
var testObj = { prop1: 10, prop2: 15, prop1: 20 }; |
Duplicating a parameter name |
Using a parameter name more than once in a function. |
SCRIPT1038: Duplicate formal parameter names not allowed in strict mode |
function testFunc(param1, param1) { return 1; }; |
Future reserved keywords |
Using a future reserved keyword as a variable or function name. |
SCRIPT1050: The use of a future reserved word for an identifier is invalid. The identifier name is reserved in strict mode. |
|
Octals |
Assigning an octal value to a numeric literal, or attempting to use an escape on an octal value. |
SCRIPT1039: Octal numeric literals and escape characters not allowed in strict mode |
var testoctal = 010;var testescape = \010; |
this |
The value ofthis is not converted to the global object when it is null orundefined. |
function testFunc() { In non-strict mode, the value of testvar is the global object, but in strict mode the value is undefined. |
|
evalas an identifier |
The string "eval" cannot be used as an identifier (variable or function name, parameter name, and so on). |
var eval = 10; |
|
Function declared inside a statement or a block |
You cannot declare a function inside a statement or a block. |
SCRIPT1047: In strict mode, function declarations cannot be nested inside a statement or block. They may only appear at the top level or directly inside a function body. |
var arr = [1, 2, 3, 4, 5]; |
Variable declared inside an evalfunction |
If a variable is declared inside anevalfunction, it cannot be used outside that function. |
SCRIPT1041: Invalid usage of 'eval' in strict mode |
eval("var testvar = 10"); testvar = 15; Indirect evaluation is possible, but you still cannot use a variable declared outside the eval function. var indirectEval = eval; indirectEval("var testvar = 10;"); document.write(testVar); This code causes an error SCRIPT5009: 'testVar' is undefined. |
Argumentsas an identifier |
The string "arguments" cannot be used as an identifier (variable or function name, parameter name, and so on). |
SCRIPT1042: Invalid usage of 'arguments' in strict mode |
var arguments = 10; |
argumentsinside a function |
You cannot change the values of members of the localargumentsobject. |
function testArgs(oneArg) { arguments[0] = 20; } In non-strict mode, you can change the value of the oneArgparameter by changing the value of arguments[0], so that the value of both oneArg and arguments[0] is 20. In strict mode, changing the value of arguments[0] does not affect the value of oneArg, because the arguments object is merely a local copy. |
|
arguments.callee |
Not allowed. |
function (testInt) { |
|
with |
Not allowed. |
SCRIPT1037: 'with' statements are not allowed in strict mode |
with (Math){ x = cos(3); y = tan(7); } |