JavaScript中的严格模式

本文同步自 个人博客,地址:http://reeoo.me/archives/strictmode.htmlhtml

什么是严格模式

咱们平时写的JavaScript代码通常都运行在正常模式中的,除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode)。看名字就知道,这种模式会让JavaScript在更严格的环境中运行。node

包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱。(github上面好多项目都是用的严格模式)git

启用严格模式

为整个脚本启用严格模式

在全部语句以前放一个特定语句 "use strict",假设有一个脚本reeoo.js,能够这样开启严格模式:程序员

"use strict";
var name = "Reeoo";
console.log(name);

BUT这种写法存在自然的坑,假如咱们要作代码合并,我如今要把heigui.jsgithub

heigui = "db";

reeoo.js进行合并,原本两个脚本分开执行是好好的,合起来就会报错。windows

Uncaught ReferenceError: heigui is not defined(…)

一个严格模式的脚本和一个非严格模式的脚本合并可能会致使非严格模式的脚本代码报错,建议代码都包在一个当即执行函数里面。浏览器

(function(){
    "use strict";
    var name = "reeoo";
})();

(function(){
    heigui = "db";
})();

这样合并以后就不会报错了。闭包

为某个函数启用严格模式

要给某个函数开启严格模式,得把"use strict"; 声明放在函数体全部语句以前就好了。app

function strictFun()
{
  // 函数级别严格模式语法
  'use strict';
  console.log('I am a strictmode function!');
}

function normalFun() { 
    console.log('I am a mormal function!');
}

Chrome中调试严格模式

我有这么一段代码:ide

'use strict'
name = "reeoo";
console.log(name)

把这段代码直接粘贴到Chrome的控制台中执行,正常状况下应该报错,可是并无报错,

ChromeConsole

很显然,严格模式下变量不适用var声明是不合法的,可是为何没有报错?

这是什么鬼,难道Chrome不支持严格模式?开什么玩笑。。。

网上搜了一下,原来Chrome的控制台的代码是运行在eval之中的,你无法对eval函数使用严格模式(应该也不彻底对,可是具体Chrome作了什么,不得而知),下图说明eval函数可使用严格模式:

NodeEval

要想在Chrome浏览器中对严格模式正常报错,须要在代码外层套一个当即执行函数,或者其它相似的措施。

(function(){
    'use strict'
    name = "reeoo";
    console.log(name) 
})()

这样就能够了

FireFox代码草稿纸调试严格模式

Chrome非要咱们包一层闭包才能跑严格模式,既然这么麻烦,有没有别的方式能够直接跑严格模式的代码呢?

FireFox有一个代码草稿纸能够直接跑,快捷键SHIFT+F4

FF代码草稿纸

严格模式到底有多严格

严格模式中一些重要的限制

1. 变量声明

不容许使用一个没有声明的变量

"use strict";
name = "reeoo";

报错(代码草稿纸,下同)

Exception: ReferenceError: assignment to undeclared variable name

2. 修改只读属性的值

"use strict";
var testObj = Object.defineProperties({}, {
    prop1: {
        value: 10,
        writable: false // 一个只读的属性
    },
    prop2: {
        get: function () {
        }
    }
});
testObj.prop1 = 20; //尝试改变prop1的值
testObj.prop2 = 30;//尝试改变prop2的值

严格模式下会报错:

Uncaught TypeError: Cannot assign to read only property 'prop1' of #<Object>

非严格模式顶多就是值赋不上去而已,并不会报错

3. 修改不可扩展的属性

表现为将属性添加到 extensible 属性设置为 false 的对象。

"use strict";
var testObj = new Object();
Object.preventExtensions(testObj);//通过这个方法处理过的对象,不影响原有对象的删除,修改.可是没法添加新的属性成员了.
testObj.name = "reeoo";

严格模式报错:

Uncaught TypeError: Can't add property name, object is not extensible

非严格模式不会报错,可是testObj也不会被扩展。

4. 删除变量、函数或参数

删除 configurable 特性设置为 false 的属性。

"use strict";
var testvar = 15,testObj={};
function testFunc() {};
delete testvar;
delete testFunc;

Object.defineProperty(testObj, "testvar", {
    value: 10,
    configurable: false
    });
delete testObj.testvar;

报错:

Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.

5. 在一个对象文本中屡次定义某个属性

严格模式下不容许一个属性有多个定义

"use strict";
var testObj = {
    prop1: 10,
    prop2: 15,
    prop1: 20
};

报错(node控制台)

Duplicate data property in object literal not allowed in strict mode

正常模式中后声明的重复的变量会覆盖前面声明的,并且不会报错。

注:这个问题在ECMAScript6中已被修复。

6. 严格模式下不容许形参参数名称重复

"use strict";
function testFunc(param1, param1) {
    return 1;
};

报错:

Uncaught SyntaxError: Duplicate parameter name not allowed in this context

7. 没法使用标识符的将来保留字,严格模式下将保留标识符名称

一下标识符(ES6中依然没有实现的)在严格模式中是不能使用的,不然也会报错。

用了就是这个下场:

Uncaught SyntaxError: Unexpected strict mode reserved word
implements
interface
package
private
protected
public
static
yield

8. 严格模式下不容许使用八进制数字参数和转义字符

"use strict";
var testoctal = 010;
var testescape = \010;

报错:

Uncaught SyntaxError: Unexpected token ILLEGAL(…)

9. 当 this 的值为 nullundefined 时,该值不会转换为全局对象

好比:

"use strict";
function testFunc() {
    return this;
}
var testvar = testFunc();

在非严格模式下,testvar 的值为全局对象window,但在严格模式下,该值为 undefined

10. 字符串"eval"不能用做标识符(变量或函数名、参数名等)

"use strict";
var eval = "hehe";
Uncaught SyntaxError: Unexpected eval or arguments in strict mode

11. 在严格模式下,函数声明没法嵌套在语句或块中。它们只能显示在顶级或直接显示在函数体中

"use strict";
var arr = [1, 2, 3, 4, 5];
var index = null;
for (index in arr) {
    function myFunc() {};
}

node控制台:

SyntaxError: In strict mode code, functions can only be declared at top level or immediately within another function.

可是这个限制已经在ES6中被修复。

12. 严格模式下eval用法无效

若是在 eval 函数内声明变量,则不能在此函数外部使用该变量。

"use strict";
eval("var testvar = 10");
console.log(testvars);
Uncaught ReferenceError: testvar is not defined

13. 严格模式下"arguments"用法无效

字符串"arguments"不能用做标识符(变量或函数名、参数名等)。

"use strict";
var arguments = 1;
Uncaught SyntaxError: Unexpected eval or arguments in strict mode

这个跟上面第10条的限制是差很少的。

14. 函数内的 arguments,没法更改arguments 对象的成员的值

"use strict";
function testArgs(oneArg) {
    arguments[0] = 20;
}

在非严格模式下,能够经过更改 arguments[0] 的值来更改 oneArg 参数的值,从而使 oneArgarguments[0] 的值都为 20。在严格模式下,更改 arguments[0] 的值不会影响 oneArg 的值,由于 arguments 对象只是一个本地副本。

15. 不容许使用arguments.callee

"use strict";
function my(testInt) {
    if (testInt-- == 0)
        return;
    arguments.callee(testInt--);
}
my(100);

用了的下场就是这样:

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

16. 不容许使用with

"use strict";
with (Math){
    x = cos(3);
    y = tan(7);
}
Uncaught SyntaxError: Strict mode code may not include a with statement

为何要使用严格模式

既然这种模式这么多限制,我为何还要用呢?闲得蛋疼吗?固然8是。

JavaScript做为一门一开始用于浏览器的脚本语言,容错性很是好,即便有时候你的代码写的不标准,也不会报错,但这有时候会变成代码隐患。开启了严格模式以后,JavaScript的一些不合理的不严谨的语法都会获得控制,让你可以更严谨的书写JavaScript代码,成为一个更好的程序员。严格模式是ES5时代的产物,ES2015已经在普及的路上,是时候使用严格模式了!

参考

  1. 严格模式

  2. 严格模式

相关文章
相关标签/搜索