理解javascript中的严格模式


Posted in Javascript onFebruary 01, 2016

一、什么是严格模式
我们平时写的JavaScript代码一般都运行在正常模式中的,除了正常运行模式,ECMAscript 5添加了第二种运行模式:”严格模式”(strict mode)。看名字就知道,这种模式会让JavaScript在更严格的环境中运行。
包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱。(github上面好多项目都是用的严格模式)
二、启用严格模式
为整个脚本启用严格模式
在所有语句之前放一个特定语句 "use strict";
假设有一个脚本reeoo.js,可以这样开启严格模式:

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

BUT这种写法存在天然的坑,假如我们要做代码合并,我现在要把heigui.js:

heigui = "db";

和reeoo.js进行合并,本来两个脚本分开执行是好好的,合起来就会报错。
Uncaught ReferenceError: heigui is not defined(…)
一个严格模式的脚本和一个非严格模式的脚本合并可能会导致非严格模式的脚本代码报错,建议代码都包在一个立即执行函数里面。

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

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

这样合并之后就不会报错了。
为某个函数启用严格模式
要给某个函数开启严格模式,得把"use strict"; 声明放在函数体所有语句之前就行了。

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

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

Chrome中调试严格模式
我有这么一段代码:

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

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

理解javascript中的严格模式

很显然,严格模式下变量不适用var声明是不合法的,但是为什么没有报错?
这是什么鬼,难道Chrome不支持严格模式?开什么玩笑。。。
网上搜了一下,原来Chrome的控制台的代码是运行在eval之中的,你没法对eval函数使用严格模式(应该也不完全对,但是具体Chrome做了什么,不得而知),下图说明eval函数可以使用严格模式:

理解javascript中的严格模式

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

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

这样就可以了
FireFox代码草稿纸调试严格模式
Chrome非要我们包一层闭包才能跑严格模式,既然这么麻烦,有没有别的方式可以直接跑严格模式的代码呢?
FireFox有一个代码草稿纸可以直接跑,快捷键SHIFT+F4

理解javascript中的严格模式

严格模式到底有多严格
严格模式中一些重要的限制

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 的值为 null 或 undefined 时,该值不会转换为全局对象
比如:

"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 参数的值,从而使 oneArg 和 arguments[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. 严格模式

原文:http://reeoo.me/archives/strictmode.html

Javascript 相关文章推荐
防止浏览器记住用户名及密码的简单实用方法
Apr 22 Javascript
高性能JavaScript DOM编程(1)
Aug 11 Javascript
jQuery的实例及必知重要的jQuery选择器详解
May 20 Javascript
jQuery增加和删除表格项目及实现表格项目排序的方法
May 30 Javascript
javascript类型系统——undefined和null全面了解
Jul 13 Javascript
深入浅析Vue组件开发
Nov 25 Javascript
Vue中使用clipboard实现复制功能
Sep 05 Javascript
Vue框架里使用Swiper的方法示例
Sep 20 Javascript
JS学习笔记之数组去重实现方法小结
May 29 Javascript
vue+webpack dev本地调试全局样式引用失效的解决方案
Nov 12 Javascript
浅谈vue的第一个commit分析
Jun 08 Javascript
javascript实现点击按钮切换轮播图功能
Sep 23 Javascript
浅析JavaScript作用域链、执行上下文与闭包
Feb 01 #Javascript
jQuery 3.0 的变化及使用方法
Feb 01 #Javascript
jQuery与Ajax以及序列化
Feb 01 #Javascript
js格式化输入框内金额、银行卡号
Feb 01 #Javascript
javascript嵌套函数和在函数内调用外部函数的区别分析
Jan 31 #Javascript
JavaScript中eval函数的问题
Jan 31 #Javascript
JS排序方法(sort,bubble,select,insert)代码汇总
Jan 30 #Javascript
You might like
探讨:使用XMLSerialize 序列化与反序列化
2013/06/08 PHP
改写ThinkPHP的U方法使其路由下分页正常
2014/07/02 PHP
2个Codeigniter文件批量上传控制器写法例子
2014/07/25 PHP
thinkphp特殊标签用法概述
2014/11/24 PHP
php获取Google机器人访问足迹的方法
2015/04/15 PHP
php 获取xml接口数据的处理方法
2018/05/31 PHP
PHP实现简单的协程任务调度demo示例
2020/02/01 PHP
jquery parent和parents的区别分析
2013/10/02 Javascript
jquery 检测元素是否存在的实例代码
2013/11/19 Javascript
仿百度联盟对联广告实现代码
2014/08/30 Javascript
JS跨域问题详解
2014/11/25 Javascript
JavaScript常用脚本汇总(三)
2015/03/04 Javascript
js实现滑动触屏事件监听的方法
2015/05/05 Javascript
javascript实现根据3原色制作颜色选择器的方法
2015/07/17 Javascript
学习JavaScript事件流和事件处理程序
2016/01/25 Javascript
详解bootstrap的modal-remote两种加载方式【强化】
2017/01/27 Javascript
使用Require.js封装原生js轮播图的实现代码
2017/06/15 Javascript
jQuery实现的鼠标滚轮控制图片缩放功能实例
2017/10/14 jQuery
使用node打造自己的命令行工具方法教程
2018/03/26 Javascript
vue打包之后生成一个配置文件修改接口的方法
2018/12/09 Javascript
微信小程序视图控件与bindtap之间的问题的解决
2019/04/08 Javascript
JS实现滑动拼图验证功能完整示例
2020/03/29 Javascript
JS实现可以用键盘方向键控制的动画
2020/12/11 Javascript
Python中的作用域规则详解
2015/01/30 Python
Windows下PyMongo下载及安装教程
2015/04/27 Python
Python 稀疏矩阵-sparse 存储和转换
2017/05/27 Python
朴素贝叶斯分类算法原理与Python实现与使用方法案例
2018/06/26 Python
python中类的属性和方法介绍
2018/11/27 Python
OpenCV3.0+Python3.6实现特定颜色的物体追踪
2019/07/23 Python
5行Python代码实现图像分割的步骤详解
2020/05/25 Python
德国游戏机商店:Konsolenkost
2019/12/08 全球购物
Napapijri西班牙在线商店:夹克、外套、运动衫等
2020/11/05 全球购物
描述RIP和OSPF区别以及特点
2015/01/17 面试题
孝敬父母的活动方案
2014/08/28 职场文书
2014年图书室工作总结
2014/12/09 职场文书
小学班主任工作经验交流材料
2015/11/02 职场文书