javascript 严格模式详解

引言

  • 严格模式是在ECMAscript 5中添加的;
  • 严格模式消除Javascript语法的一些不合理、不严谨之处,消除代码运行的一些不安全之处;
  • 严格模式提高编译器效率,增加运行速度;
  • 如果不主动声明,编译器默认是正常模式;

进入严格模式的方式

  • 在脚本第一行声明,则整个脚本都将以”严格模式”运行,如果这行语句不在第一行,则无效,整个脚本以”正常模式”运行;
  • 将”use strict”放在函数体的第一行,则整个函数以”严格模式”运行;
1
2
"use strict";
console.log("这是严格模式。");
1
2
3
4
function strict(){
  "use strict";
  return "这是严格模式";
}

严格模式”严格”了哪些语法行为

  • 全局变量必须显式声明
1
2
"use strict";
i=1; //Uncaught ReferenceError: i is not defined
1
2
3
4
5
6
"use strict";
(function() {
var a = b = 5; //由于b没有用var关键自定义,严格模式下报错
})();

console.log(b); //正常模式下b是全局变量,输出5
1
2
3
4
5
"use strict";
var arr = new Array(1,2,3);
for(i =0; i<arr.length; i++){ //Uncaught ReferenceError: i is not defined
console.log(arr[i]);
}
  • 严格模式下不能使用with语句
1
2
3
4
5
6
7
8
"use strict"
var o = document.createElement("div");
with(o){ //Uncaught SyntaxError: Strict mode code may not include a with statement
style.width = "100px";
style.height = "100px";
style.backgroundColor = "#000";
}
document.body.appendChild(o);
  • 严格模式下,eval作用域发生变化
    • 正常模式下,eval语句不形成单独的作用域,eval就相当于将其中的语句直接写到js中;
    • 严格模式下,eval语句形成了自己的作用域;
1
2
3
var x = 2;
console.info(eval("var x = 5; x")); // 5
console.info(x); // 5
1
2
3
4
"use strict";
var x = 2;
console.info(eval("var x = 5; x")); // 5
console.info(x); // 2

严格模式增强了哪些安全措施

  • this关键字禁止指向全局对象
1
2
3
4
5
6
7
8
function f(){
return !this; // 返回false,因为"this"指向全局对象,"!this"就是false
}

function f(){
"use strict";
return !this; // 返回true,因为严格模式下,this的值为undefined,所以"!this"为true
}
1
2
3
4
5
"use strict";
function f(){
this.name = 1; //Uncaught TypeError: Cannot set property 'name' of undefined
};
f();
  • 限制使用函数内置对象
    • argument对象(比如遍历argument输出传入参数值)及其属性(比如argument.length)仍可使用, 但caller、callee不能使用;
    • argument对象不再追踪参数的变化情况;
1
2
3
4
5
6
7
8
9
10
11
12
"use strict";
function testCaller() {
alert(testCaller.caller); //报错
alert(arguments.callee); //报错
}

function aCaller() {
alert(arguments.length); //由于传入参数个数为2,故输出2
alert(arguments.caller); //报错
testCaller();
}
aCaller("haha","heihei");
1
2
3
4
5
6
7
function f(a) {
/*"use strict";*/
a = 2;
alert(arguments.caller);
return [a, arguments[0]];
}
alert(f(1)); // 正常模式为[2,2], 严格模式为[2,1]
  • 禁止随意删除变量
    • 严格模式下无法删除变量;
    • 只有configurable设置为true的对象属性,才能被删除;
1
2
3
4
5
6
7
8
"use strict";
var x;
delete x; // 语法错误
var o = Object.create(null, {'x': {
    value: 1,
    configurable: true
}});
delete o.x; // 删除成功
  • 另外
    • 严格模式下,一个对象不能有重名的属性;
    • 严格模式下,一个函数不能传入重名的参数;
    • 严格模式下,禁止八进制表示法;
1
2
3
"use strict";
var o = {p:1,p:2}; //严格模式下报错
alert(o.p); //正常模式下输出2
1
2
"use strict";
var i = 0100; //Uncaught SyntaxError: Octal literals are not allowed in strict mode.

严格模式下的对象操作

  • 正常模式下,对一个对象的只读属性进行赋值,不会报错,只会默默地失败,严格模式下将报错;
1
2
3
4
"use strict";
var o = {};
Object.defineProperty(o, "v", { value: 1, writable: false });
o.v = 2; // 报错
  • 严格模式下,对一个使用getter方法读取的属性进行赋值,会报错;
1
2
3
4
5
"use strict";
var o = {
  get v() { return 1; }
};
o.v = 2; // 报错
  • 严格模式下,对禁止扩展的对象添加新属性,会报错;
1
2
3
4
"use strict";
var o = {};
Object.preventExtensions(o);
o.v = 1; // 报错
  • 严格模式下,删除一个不可删除的属性,会报错;
1
2
"use strict";
delete Object.prototype; // 报错

保留字

  • 为了向将来Javascript的新版本过渡,严格模式新增了一些保留字:implements, interface, let, package, private, protected, public, static, yield;
  • 用这些新增保留字做变量名,正常模式不会报错,严格模式报错;
1
2
3
"use strict"
var implements = 1; //Uncaught SyntaxError: Unexpected strict mode reserved word
alert(implements);
您的支持是对我最大的鼓励!