理解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 相关文章推荐
破除一些网站复制、右键限制
Nov 04 Javascript
在图片上显示左右箭头类似翻页的代码
Mar 04 Javascript
jQuery图片滚动图片的效果(另类实现)
Jun 02 Javascript
javascript获得网页窗口实际大小的示例代码
Sep 21 Javascript
ie8本地图片上传预览示例代码
Jan 12 Javascript
jQuery幻灯片带缩略图轮播效果代码分享
Aug 17 Javascript
基于AngularJS实现iOS8自带的计算器
Sep 12 Javascript
jQuery easyui刷新当前tabs的方法
Sep 23 Javascript
angular.js指令中transclude选项及ng-transclude指令详解
May 24 Javascript
JavaScript闭包和回调详解
Aug 09 Javascript
JavaScript 判断对象中是否有某属性的常用方法
Jun 14 Javascript
js实现网页同时进行多个倒计时功能
Feb 25 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
延长phpmyadmin登录时间的方法
2011/02/06 PHP
php表单提交问题的解决方法
2011/04/12 PHP
PHP设计模式之迭代器模式的深入解析
2013/06/13 PHP
使用Linux五年积累的一些经验技巧
2013/06/20 PHP
php管理nginx虚拟主机shell脚本实例
2014/11/19 PHP
smarty表格换行实例
2014/12/15 PHP
php通过function_exists检测函数是否存在的方法
2015/03/18 PHP
php版微信返回用户text输入的方法
2016/11/14 PHP
理解JavaScript中的事件
2006/09/23 Javascript
破除一些网站复制、右键限制
2006/11/04 Javascript
jQuery 锚点跳转滚动条平滑滚动一句话代码
2010/04/30 Javascript
Jquery + Ajax调用webService实例代码(asp.net)
2010/08/27 Javascript
探讨js字符串数组拼接的性能问题
2014/10/11 Javascript
js实现鼠标感应向下滑动隐藏菜单的方法
2015/02/20 Javascript
Node.js本地文件操作之文件拷贝与目录遍历的方法
2016/02/16 Javascript
JavaScript的this关键字的理解
2016/06/18 Javascript
相册展示PhotoSwipe.js插件实现
2016/08/25 Javascript
JS中with的替代方法与String中的正则方法详解
2016/12/23 Javascript
jquery事件与绑定事件
2017/03/16 Javascript
underscore之function_动力节点Java学院整理
2017/07/11 Javascript
vue + webpack如何绕过QQ音乐接口对host的验证详解
2018/07/01 Javascript
vuex 解决报错this.$store.commit is not a function的方法
2018/12/17 Javascript
ios中视频的最后一桢问题解决
2019/05/14 Javascript
Postman内建变量常用方法实例解析
2020/07/28 Javascript
python中pycurl库的用法实例
2014/09/30 Python
Pycharm安装Qt Design快捷工具的详细教程
2020/11/18 Python
Python LMDB库的使用示例
2021/02/14 Python
Brookstone美国官网:独特新奇产品
2017/03/04 全球购物
简单说下OSPF的操作过程
2014/08/13 面试题
什么是makefile? 如何编写makefile?
2013/01/02 面试题
中学生演讲稿
2014/04/26 职场文书
2014年六一儿童节演讲稿
2014/05/23 职场文书
教师求职信范文
2014/05/24 职场文书
结婚保证书(三从四德)
2015/02/26 职场文书
Winsows11性能如何? win11性能测评多核竟比Win10差了10%
2021/11/21 数码科技
SpringBoot2零基础到精通之数据库专项精讲
2022/03/22 Java/Android