1. “use strict” 开启严格模式
(1)给script标签开启严格模式
(2)给function开启严格模式function() {“use strict”; }
2. 严格模式的不同之处
(1)将拼写错误转换成异常
a. 无法再意外得创建全局变量
"use strict";
var hei;
hie = 1;
Uncaught ReferenceError: hie is not defined
b. 静默失败的赋值抛出异常
静默失败(silently fall):不报错也没有任何效果。给不可写属性赋值,给只读属性赋值,给不可扩展对象的新属性赋值,这些情况都可以引起静默失败。
"use strict";
var fixed = {};
Object.preventExtensions(fixed);
fixed.addProp = "hi";
Uncaught TypeError: Cannot add property newProp, object is not extensible
c. 试图删除不可删除的属性时会抛出异常
"use strict";
delete Object.prototype;
Uncaught TypeError: Cannot delete property ‘prototype’ of function Object() { [native code] }
d. 在Gecko版本34之前,要求一个对象内的所有属性名在对象内是唯一的,现在已经没有这个bug了。
"use strict";
var obj = {p: 1, p: 2};
e. 要求函数的参数名唯一
非严格模式,同名的参数后者会覆盖前者,但是前者还是可以通过 arguments[i] 来访问。在严格模式中,有语法错误
function sum (a, a, c) {
"use strict";
return a + b + c;
}
Uncaught SyntaxError: Duplicate parameter name not allowed in this context
f. 禁止八进制数字语法
浏览器支持八进制语法;
var a = 010;
console.log(a); // a = 8;
ES6支持为一个数字加“0”的前缀表示八进制。但是有些开发者会省略掉”0”,这样可能会导致错误,所以严格模式是禁止八进制的。会抛出语法错误。
"use strict";
var a = 010;
Uncaught SyntaxError: Octal literals are not allowed in strict mode.
g. 禁止设置primitive值的属性
不采用严格模式,设置属性的操作会被忽略;采用严格模式,将抛出TypeError错误。
primitive(原始)值或primitive数据类型不是一个对象,没有methods。在JavaScript中,有6种primitive数据类型: string,number, boolean, null, undefined, symbol(ES6)
"use strict";
false.true = '';
Uncaught TypeError: Cannot create property ‘true’ on boolean ‘false’
(2). 简化变量的使用
简化了代码中变量名称映射到变量定义的方式。有利于编译器的优化。
a. 禁止使用with。
with用于设置特定对象的作用域,也就是with块里面的所有变量都是优先在传入的对象属性中查找,找不到再找作用域之外的。
var a = 123;
var b = {a: 321};
with (b) {
console.log(a); // 321
}
var d = {};
with (d) {
console.log(a);// 123
}
with引起的问题是块内的任何名称可以映射到with传进来的对象的属性,也可以映射到包围这个块的作用域内的变量,甚至是全局变量,这一切都是在运行时决定的。为了优化,所以禁用了with。
"use strict";
var x = 1;
var obj = {x: 2};
with (obj) {
console.log(x);
}
Uncaught SyntaxError: Strict mode code may not include a with statement
一种替代with 的方法是,将目标对象赋值给一个短命名变量,然后访问变量上的相应属性。
b. 严格模式下,eval 不再为上层范围(surrounding scope,也就是包围eval代码块的范围)引入新变量。
eval(string),计算某个字符串,并且执行其中的JavaScript代码。
c. 严格模式禁止删除声明变量。
非严格模式
var a = 1;
delete a;
console.log(a); // a = 1
严格模式
"use strict";
var a = 1;
delete a;
Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
(3). 让eval 和arguments 变得简单
a. 名称eval 和 arguments 不能通过程序语法被绑定或者是赋值。
"use strict";
eval = 17;
arguments ++;
Uncaught SyntaxError: Unexpected eval or arguments in strict mode
b. 严格模式下,参数的值不会随arguments 对象的值改变而改变。
非严格模式下
function f(a) {
a = 42;
return [a, arguments[0]];
}
var pair = f(17);
console.log(pair[0]); // 42
console.log(pair[1]);// 42
严格模式下
function f(a) {
"use strict";
a = 42;
return [a, arguments[0]];
}
var pair = f(17);
console.log(pair[0]); // 42
console.log(pair[1]);// 17
c. 不再支持arguments.callee。
非严格模式下,arguments.callee指向当前正在执行的函数。
严格模式下:
"use strict";
function f() {
return arguments.callee;
}
Uncaught TypeError: ‘caller’, ‘callee’, and ‘arguments’ properties may not be accessed on strict mode functions or the arguments objects for calls to them
(4). 安全的JavaScript
a. 严格模式下通过this传递给一个函数的值,不会被强制性转换为一个对象。如果没有指定this,它的值是undefined。
非严格模式
function fun() {return this;}
console.log(fun()); // Window
console.log(fun().call(2)); // Number
console.log(fun().apply(null)); // Window
console.log(fun().call(undefined)); // Window
console.log(fun().bind(true)); // Boolean
严格模式
"use strict";
function fun() {return this;}
console.log(fun()); // undefined
console.log(fun().call(2)); // 2
console.log(fun().apply(null)); // null
console.log(fun().call(undefined)); // undefined
console.log(fun().bind(true)); // true
b. 严格模式下再也不能通过广泛实现的ECMAScript游走于JavaScript栈中。
比如,一个函数fun 它的 fun.caller(返回最后一个调用fun的函数),fun.arguments都是不可删除的属性,而且在取值和存值的时候会报错。
非严格模式下:
function b() {
console.log(b.caller);
console.log(b.arguments);
}
function a() {
b();
}
a();
严格模式下:
Uncaught TypeError: ‘caller’ and ‘arguments’ are restricted function properties and cannot be accessed in this context.
c. 严格模式下arguments不会再提供访问与调用这个函数相关变量的途径。
arguments.caller对象,存储的属性指向那个函数的变量。arguments.caller是不可删除的属性,而且在取值和存值的时候会报错。
非严格模式下:
function fun(a, b) {
var v = 2;
return arguments.caller;
}
console.log(fun(1, 2)); // undefined
严格模式:
自己尝试的结果跟非严格模式一样,跟文档中不一样,为啥?
(5). 为未来的ECMAScript版本铺平道路
a. 以下保留字在严格模式下将不能作为变量名或者是形参。
implements, interface, let, package, private, protected, public, static, yield
b. 严格模式禁止了不在脚本或者是函数层面上的函数声明。
非严格模式下,在哪儿都是可以声明函数的。例如:
var flag = true;
if (flag) {
function change() {
flag = false;
}
change();
}
在严格模式下,是不建议这么做的。
3.浏览器的严格模式
主流浏览器都已经支持严格模式,但是有大量浏览器版本部分支持或者是根本不支持严格模式。
4. 其他
学习文档: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode
测试浏览器: chrome(Version 60.0.3112.113 (Official Build) (64-bit))