跳到主要内容

ES5 严格模式

年份ECMA 版本
19971.0 发布
19982.0 发布
19993.0 JS 通行标准
20074.0 草案 雅虎、微软、谷歌反对,只有 Mozilla 支持该草案
2008终止 4.0 草案,求同存异后,将可改善部分纳入 3.1,发布 3.1
20095.0 发布,争议的 Harmony 分为 JS.NEXT 和 JS.NEXT.NEXT
20115.1 发布,成为 ISO 国际标准,与 3.0 地位相同,几乎基于 3.0
2013ES6 版本不再新增内容,ES6 等同于 JS.NEXT
2013ES6 草案发布
2015ES6 正式发布,命名为 ECMAScript2015
JS.NEXT.NEXT 更名为 ES7

从 ES5 开始,JavaScript 提供了两种运行模式,即正常模式和严格模式。需要注意的是,IE9 及以下版本的 IE 浏览器不支持严格模式。

严格模式的使用

使用字符串在全局进行声明​

'use strict';

使用 'use strict' 作为表达式,不会导致报错。即使浏览器不支持严格模式,也不会出现错误。

在函数内部使用​

在企业开发中,通常在函数内部使用严格模式,全局使用较为少见。

(function () {
'use strict';
// 函数内部代码
})();

严格模式的作用

with 语句​

with 语句能够改变作用域,填入作用域名称后,会在该作用域中查找变量。此外,使用 with 会增加作用域解析的开销,影响性能。

var globalA = '全局';
var obj = {
a: 'obj中的a',
};

function test() {
var functionA = 'test函数中的a';
with (obj) {
console.log(a);
}
}
test();

在严格模式下的 with​

严格模式禁止使用 with 语句,尝试使用会导致语法错误。

'use strict';
var globalA = '全局';
var obj = {
a: 'obj中的a',
};

function test() {
var functionA = 'test函数中的a';
with (obj) {
console.log(a);
}
}
test();

运行上述代码会抛出以下错误:

Uncaught SyntaxError: Strict mode code may not include a with statement

命名空间

在开发中,可能会出现同名变量或函数的情况。

function test() {
console.log(1);
}

function test() {
console.log(2);
}

test();

上述代码会打印出第二个 test 函数的结果。

解决命名冲突的方法​

通过命名空间或模块化开发,可以避免命名冲突。

window.onload = function () {
init();
};

function init() {
initSlider();
initSidebar();
}

var initSlider = (function () {
var sliderValue = 1;
console.log(sliderValue);
})();

var initSidebar = (function () {
var sidebarValue = 1;
console.log(sidebarValue);
})();

未使用模块化时的命名空间管理​

在早期多人协作开发中,可以通过对象嵌套的方式管理命名空间,防止命名冲突。

var namespace = {
header: {
Jenny: {
a: 1,
b: 2,
},
Ben: {
a: 3,
b: 4,
},
},
sidebar: {
Crystal: {
a: 5,
b: 6,
},
},
};

// 使用命名空间访问变量
console.log(namespace.header.Ben.a);

caller 和 callee

在严格模式下,caller 和 callee 属性无法访问。

'use strict';

function test() {
console.log(arguments.callee);
}
test(1);

执行上述代码会抛出以下错误:

Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

严格模式下的变量声明

在严格模式下,必须显式声明变量,否则会导致错误。

'use strict';
var a = (b = 1);

执行上述代码会抛出错误:

'use strict';

function test() {
var a = (b = 1);
}
test();

执行上述代码同样会抛出错误:

严格模式下的 this

'use strict';
console.log(this);

在全局环境中,this 指向 window 对象。

函数内部的 this​

在严格模式下,未绑定的 this 为 undefined。

'use strict';

function test() {
console.log(this);
}
test();

上述代码输出 undefined。

严格模式下的函数形参

严格模式下,函数参数不能有重复的名称。

'use strict';

function test(a, a) {
console.log(a, a);
}
test(1, 2);

执行上述代码会抛出语法错误:

严格模式下的对象属性​

在严格模式下,对象中不允许存在重复的属性名。

'use strict';
var obj = {
a: 1,
a: 2,
};
console.log(obj.a);

上述代码不会报错,但只能访问到最后一个属性值。

eval 函数

在严格模式下,eval 拥有独立的作用域,无法向外部作用域添加变量。

'use strict';
eval('var a = 1; console.log(a);');
console.log(a);

上述代码在严格模式下,a 不会被定义在全局作用域,第二个 console.log(a) 会导致错误。