对于 JavaScript
严格模式与非严格模式的区别,强烈建议大家去查看权威文档 MDN: 严格模式,不要乱找百度,本文也主要是参考了 MDN
上对 JS 严格模式
的介绍。
首先,严格模式通过抛出错误来消除一些原有的静默错误。
其次,严格模式修复了一些导致JavaScript引擎难以执行优化的缺陷:有时候,相同的代码,严格模式可以比非严格模式下运行的更快。
第三,严格模式禁用了在ECMAScript的未来版本中可能会定义的一些语法。
1、使用严格模式
- 函数中使用
funtion () {
'use strict'; //或者是"use strict";
}
- 整个脚本中使用:在这个JavaScript文件开头写
'use strict';
(或者是"use strict";
)
2、怎么合理的使用严格模式
不推荐在整个脚本中使用严格模式
,这种语法存在缺陷,有一个大型网站已经被坑倒了。试想合并一个严格模式的脚本和一个非严格模式的脚本:合并后脚本的代码看起来是严格模式。反之亦然:非严格合并严格看起来是非严格的。
严格与严格,非严格与非严格合并都没问题,只有严格与非严格合并是有可能有问题。建议按照一个个函数去开启严格模式。
你可以将整个脚本的内容用一个函数包括起来,然后在这个外部函数中使用严格模式。这样就可以消除合并的问题,但是这就意味着您必须要在函数作用域外声明一个全局变量。
3、严格模式与非严格模式的不同
1.严格模式下,不允许使用with
。
!function () {
with({ x: 1 }) {
console.log(x); //1
}
}()
!function () {
'use strict';
with({ x: 1 }) {
console.log(x); //SyntaxError
}
}()
一种取代 with 的简单方法
是,将目标对象赋给一个短命名变量,然后访问这个变量上的相应属性。
p.s.:解释下!function () {}();
解释器在解释一个语句时,如果以function开头,就会理解为函数声明。
而前面加一个"!"
可以让解释器理解为函数表达式,这样就可以立即调用
了。
2.严格模式下,不允许给未声明的变量赋值
。
3.严格模式下,arguments变为参数的静态副本。
非严格模式下,arguments对象里的元素和对应的参数是指向同一个值的引用
!function(a) {
arguments[0] = 100;
console.log(a); //100
}(1);
!function(a) {
'use strict';
arguments[0] = 100;
console.log(a); //1
}(1);
但是:传的参数
是对象
除外。arguments和形参共享传递。
!function(a) {
'use strict';
console.log(a.x); //1
arguments[0].x = 100;
console.log(a.x); //100
}({ x: 1});
4.严格模式下,删除参数名,函数名报错
。非严格模式返回false,静默失败。(静默失败:不报错也没有任何效果)
!function(a) {
console.log(a); //1
console.log(delete a); //false
console.log(a); //1
}(1);
!function(a) {
'use strict';
console.log(a); //1
delete a; //SyntaxError(语法错误)
console.log(a); //1
}(1)
5.严格模式下,函数参数名重复报错
。非严格模式最后一个重名参数会覆盖之前的重名参数。
!function (a, a, b) {
console.log(a + b); //5
}(1, 2, 3);
!function (a, a, b) {
'use strict';
console.log(a + b); //SyntaxError
}(1, 2, 3);
6.严格模式下,删除不可配置(configurable=false)的属性报错
。非严格模式返回false,静默失败。
!function (a){
var obj={ };
Object.defineProperty(obj,'a',{ configurable: false });
console.log(delete obj.a); //flase
}(1);
!function (a){
'use strict';
var obj={ };
Object.defineProperty(obj, 'a', { configurable: false });
console.log(delete obj.a); //TypeError
}(1);
7.严格模式下,修改不可写(writable=false)的属性报错
。
!function () {
var obj = { a: 1 };
Object.defineProperty(obj, 'a', { writable: false });
obj.a = 2;
console.log(obj.a); //1 //证明没有被修改
}();
!function () {
'use strict';
var obj = { a: 1 };
Object.defineProperty(obj, 'a', { writable: false});
obj.a = 2; //TypeError
}();
8.严格模式下,对象字面量重复属性名报错
。
!function() {
var obj = { x: 1, x: 2 };
console.log(obj.x); //2
}();
!function() {
'use strict';
var obj = { x: 1, x: 2 };
console.log(obj.x); //IE10+报错。IE7~9、Chrome、FF不报错,结果为:2
}();
亲测:IE10+报错:strict 模式下不允许一个属性有多个定义。IE7~9,Chrome,FF不报错。其他浏览器未测。
9.严格模式下,禁止八进制字面量
。
!function (){
console.log(0123); //83
}();
!function (){
'use strict';
console.log(0123); //SyntaxError
}();
10.严格模式下,eval,arguments成为关键字,不能用作变量,函数名
。
11.严格模式下,eval变成了独立作用域
。
!function() {
eval('var evalVal = 2;');
console.log(typeof evalVal); //number
}();
!function() {
'use strict';
eval('var evalVal = 2;');
console.log(typeof evalVal); //undefined
}();
12.严格模式下,给只读属性赋值报错
。
!function () {
'use strict';
var obj = { get x() { return 17; } };
obj.x = 5; //TypeError
}();
13.严格模式下,给不可扩展对象的新属性赋值报错
。
!function () {
'use strict';
var fixed = { oldProp: "hello" };
Object.preventExtensions(fixed);
fixed.newProp = "world"; //TypeError
}();
14.ES6中,严格模式下,禁止设置五种基本类型值的属性
。
!function () {
'use strict';
undefined.aaa = 'aaa'; //TypeError
null.bbb = 'bbb'; //TypeError
false.ccc = 'ccc'; //TypeError
(123).ddd = 'ddd'; //TypeError
"hello".eee = 'eee'; //TypeError
}();
12.严格模式下,一般函数调用(不是对象的方法调用,也不使用apply/call/bind等修改this),this指向undefined,而不是全局对象
。
!function () {
function fun() { return this; }
console.log( fun() ); //Window
}();
!function () {
'use strict';
function fun() { return this; }
console.log( fun() ); //undefined
}();
注意:这一点网上好多说的是this
会指向null
,这是不对的,查看了MDN之后,上面明确写出this
指向undefined
。Chrome下亲测也是如此。
13.严格模式下,使用apply/call/bind,当传入参数是null/undefined时,this指向null/undefined,而不是全局对象
。
!function () {
function fun() { return this; }
console.log( fun.apply(null) ); //Window
console.log( fun.apply(undefined) ); //Window
console.log( fun.call(null) ); //Window
console.log( fun.call(undefined) ); //Window
console.log( fun.bind(null)() ); //Window
console.log( fun.bind(undefined)() ); //Window
}();
!function () {
'use strict';
function fun() { return this; }
console.log( fun.apply(null) ); //null
console.log( fun.apply(undefined) ); //undefined
console.log( fun.call(null) ); //null
console.log( fun.call(undefined) ); //undefined
console.log( fun.bind(null)() ); //null
console.log( fun.bind(undefined)() ); //undefined
}();
14.严格模式下,不再支持arguments.callee
。非严格模式下,arguments.callee指向当前正在执行的函数。这个作用很小:直接给执行函数命名就可以了!此外,arguments.callee 十分不利于优化,例如内联函数,因为 arguments.callee 会依赖对非内联函数的引用。在严格模式下,arguments.callee 是一个不可删除属性,而且赋值和读取时都会抛出异常:
!function () {
'use strict';
var fun = function () { return arguments.callee; };
fun(); //TypeError
}();
15.严格模式下,不再支持arguments.caller
。在一些旧时的ECMAScript实现中arguments.caller曾经是一个对象,里面存储的属性指向那个函数的变量。这是一个安全隐患,因为它通过函数抽象打破了本来被隐藏起来的保留值;它同时也是引起大量优化工作的原因。出于这些原因,现在的浏览器没有实现它。但是因为它这种历史遗留的功能,arguments.caller在严格模式下同样是一个不可被删除的属性,在赋值或者取值时会报错:
!function () {
"use strict";
function fun(a, b) {
var c = 12;
return arguments.caller; //IE10+报错。IE7~9、Chrome、FF不报错。
}
console.log(fun(1, 2)); //在不报错的浏览器下,结果是:undefined
}();
亲测:IE10+报错:strict 模式下不允许访问函数或参数对象的“caller”属性。IE7~9、Chrome、FF不报错。其他浏览器未测。
16.严格模式下,一些保留字
。
在严格模式中一部分字符变成了保留的关键字。这些字符包括implements
, interface
, let
, package
, private
, protected
, public
, static
和 yield
。在严格模式下,你不能再用这些名字作为变量名或者形参名。
17.严格模式下,禁止了不在脚本或者函数层面上的函数声明
。
!function () {
"use strict";
if (true) {
function fun() { }
console.log( fun() ); //IE10报错。IE11、IE7~9、Chrome、FF不报错。
}
for (var i = 0; i < 5; i++) {
function fun2() { }
console.log( fun2() ); //IE10报错。IE11、IE7~9、Chrome、FF不报错。
}
function fun3() { // 合法
function fun4() { } //同样合法
}
}();
亲测:IE10报错。IE11、IE7~9、Chrome、FF不报错。其他浏览器未测。
主流浏览器现在实现了严格模式。但是不要盲目的依赖它,因为市场上仍然有大量的浏览器版本只部分支持严格模式或者根本就不支持。谨慎地使用严格模式!
以上 ?
还没有人抢沙发呢~