Javascript严格模式总结

1,201 阅读5分钟

严格模式是什么

ECMAScript 5的严格模式是采用具有限制性JavaScript变体的一种方式,从而使代码显示地 脱离“马虎模式/稀松模式/懒散模式“(sloppy)模式。

严格模式对正常的 JavaScript语义做了一些更改。

  1. 严格模式通过抛出错误来消除了一些原有静默错误。
  2. 严格模式修复了一些导致JavaScript引擎难以执行优化的缺陷:有时候,相同的代码,严格模式可以比非严格模式下运行得更快。
  3. 严格模式禁用了在ECMAScript的未来版本中可能会定义的一些语法。

调用严格模式

严格模式可以应用到整个脚本或个别函数中。

  1. 为脚本开启严格模式

为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句 "use strict"; (或 'use strict';)

(function(){
	"use strict";
	var v = "Hi!  I'm a strict mode script!";
})();
  1. 为函数开启严格模式
function strict() {
  // 函数级别严格模式语法
  'use strict';
  function nested() { 
    return "And so am I!"; 
  }
  return "Hi!  I'm a strict mode function!  " + nested();
}

function notStrict() { 
  return "I'm not strict."; 
}

严格模式中的变化

  1. 不允许使用未声明的变量 (严格模式中意外创建全局变量被抛出错误替代)
(function(){
	"use strict";
	x = 3.14;  // Uncaught ReferenceError: x is not defined
})();
  1. 不允许删除变量或对象(严格模式禁止删除声明变量)
(function(){
	"use strict";
	var x = 3.14;
	delete x; //Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
})();
  1. 不允许删除函数
(function(){
	"use strict";
	function x(p1, p2) {};
	delete x; //Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
})();
  1. 不允许变量重名(严格模式要求函数的参数名唯一)
(function(){
	"use strict";
	function x(p1,p1){}; //Uncaught SyntaxError: Duplicate parameter name not allowed in this context
})();
  1. 不允许使用八进制(严格模式禁止八进制数字语法)
(function(){
	"use strict";
	var x = 010; //Uncaught SyntaxError: Octal literals are not allowed in strict mode.
})();
  1. 不允许使用转义字符
(function(){
	"use strict";
	var x = \010; //Uncaught SyntaxError: Invalid or unexpected token
})();
  1. 不允许对不可写属性赋值
(function(){
	"use strict";

	//给不可写属性赋值
	var obj = {};
	Object.defineProperty(obj, "x", {value:0, writable:false});
	obj.x = 3.14; //Uncaught TypeError: Cannot assign to read only property 'x' of object '#<Object>'
})();
  1. 不允许对一个使用getter方法读取的属性进行赋值 (只读属性赋值)
(function(){
	"use strict";

	//给只读属性赋值
	var obj = {get x() {return 0} };
	obj.x = 3.14; //Uncaught TypeError: Cannot set property x of #<Object> which has only a getter
})();
  1. 不允许给不可扩展对象的新属性赋值
(function(){
	"use strict";
  // 给不可扩展对象的新属性赋值
	var fixed = {};
	Object.preventExtensions(fixed);
	fixed.newProp = "ohai"; //Uncaught TypeError: Cannot add property newProp, object is not extensible
})();
  1. 不允许删除一个不允许删除的属性
(function(){
	"use strict";
	delete Object.prototype; //Uncaught TypeError: Cannot delete property 'prototype' of function Object() { [native code] }
})();
  1. 变量名不能使用 "eval" 字符串
(function(){
	"use strict";
	var eval = 3.14; //Uncaught SyntaxError: Unexpected eval or arguments in strict mode
})();
  1. 变量名不能使用 "arguments" 字符串
(function(){
	"use strict";
	var arguments = 3.14; //Uncaught SyntaxError: Unexpected eval or arguments in strict mode
})();

//名称 eval 和 arguments 不能通过程序语法被绑定(be bound)或赋值. 以下的所有尝试将引起语法错误:
(function(){
	"use strict";
	eval = 17;
	arguments++;
	++eval;
	var obj = { set p(arguments) { } };
	var eval;
	try { } catch (arguments) { }
	function x(eval) { }
	function arguments() { }
	var y = function eval() { };
	var f = new Function("arguments", "'use strict'; return 17;");
})();
  1. 不允许使用以下这种语句(严格模式禁用 with)
(function(){
	"use strict";
	with (Math){x = cos(2)}; //Uncaught SyntaxError: Strict mode code may not include a with statement
})();

(function(){
	"use strict";
	var x = 17;
	with (obj) { // !!! 语法错误
	  // 如果没有开启严格模式,with中的这个x会指向with上面的那个x,还是obj.x?
	  // 如果不运行代码,我们无法知道,因此,这种代码让引擎无法进行优化,速度也就会变慢。
	  x;
	}
})();
  1. 由于一些安全原因,在作用域 eval() 创建的变量不能被调用
(function(){
	"use strict";
	eval("var x = 2");
	console.log(x); //Uncaught ReferenceError: x is not defined
})();
  1. 禁止this关键字指向全局对象
function f(){
    return !this;
} 
// 返回false,因为"this"指向全局对象,"!this"就是false

function f(){ 
    "use strict";
    return !this;
} 
// 返回true,因为严格模式下,this的值为undefined,所以"!this"true。

//使用构造函数时,如果忘了加new,this不再指向全局对象,而是报错。
function f(){
    "use strict";
    this.a = 1;
};
f();// Uncaught TypeError: Cannot set property 'a' of undefined
  1. 保留关键字

严格模式中一部分字符变成了保留的关键字。这些字符包括implements, interface, let, package, private, protected, public, static和yield。在严格模式下,你不能再用这些名字作为变量名或者形参名。

(function(){
	"use strict";
	var implements; //Uncaught SyntaxError: Unexpected strict mode reserved word
})();
  1. ECMAScript 6中的严格模式禁止设置primitive值的属性
(function() {
  "use strict";
  false.true = ""; //Uncaught TypeError: Cannot create property 'true' on boolean 'false'
  (14).sailing = "home"; //Uncaught TypeError: Cannot create property 'sailing' on number '14'
  "with".you = "far away"; //Uncaught TypeError: Cannot create property 'you' on string 'with'
})();
  1. 严格模式下,参数的值不会随 arguments 对象的值的改变而变化
function f(a) {
  "use strict";
  a = 42;
  return [a, arguments[0]];
}
var pair = f(17);
console.assert(pair[0] === 42);
console.assert(pair[1] === 17);
  1. 不再支持 arguments.callee

在严格模式下,arguments.callee 是一个不可删除属性,而且赋值和读取时都会抛出异常。

(function(){
	"use strict";
	var f = function() { return arguments.callee; };
	f(); //Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
})();
  1. 不支持fun.caller和fun.arguments

如果fun在严格模式下,那么fun.caller和fun.arguments都是不可删除的属性而且在存值、取值时都会报错。

function restricted() {
  "use strict";
  restricted.caller;    //Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
  restricted.arguments; // 抛出类型错误
}

function privilegedInvoker() {
  return restricted();
}

privilegedInvoker();

More

MDN严格模式
developer.mozilla.org/zh-CN/docs/…

Javascript 严格模式详解
www.ruanyifeng.com/blog/2013/0…

JavaScript 严格模式(use strict)
www.runoob.com/js/js-stric…