理解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 相关文章推荐
通过复制Table生成word和excel的javascript代码
Jan 20 Javascript
ExtJS 刷新后如何默认选中刷新前最后一次选中的节点
Apr 03 Javascript
javascript使用smipleChart实现简单图表
Jan 02 Javascript
javascript包装对象实例分析
Mar 27 Javascript
javascript实现省市区三级联动下拉框菜单
Nov 17 Javascript
jQuery实现的AJAX简单弹出层效果代码
Nov 26 Javascript
浅谈Javascript中的12种DOM节点类型
Aug 19 Javascript
jQuery动态添加与删除tr行实例代码
Oct 18 Javascript
Angular.js中window.onload(),$(document).ready()的写法浅析
Sep 28 Javascript
详解Vue调用手机相机和相册以及上传
May 05 Javascript
Vue中关闭弹窗组件时销毁并隐藏操作
Sep 01 Javascript
vue打开其他项目页面并传入数据详解
Nov 25 Vue.js
浅析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
我的论坛源代码(九)
2006/10/09 PHP
php_pdo 预处理语句详解
2016/11/21 PHP
php实现数组纵向转横向并过滤重复值的方法分析
2017/05/29 PHP
JavaScript 无符号右移赋值操作
2009/04/17 Javascript
javaScript 判断字符串是否为数字的简单方法
2009/07/25 Javascript
JS 遮照层实现代码
2010/03/31 Javascript
jQuery 打造动态下滑菜单实现说明
2010/04/15 Javascript
parseInt parseFloat js字符串转换数字
2010/08/01 Javascript
JavaScript indexOf方法入门实例(计算指定字符在字符串中首次出现的位置)
2014/10/17 Javascript
jQuery遍历json中多个map的方法
2015/02/12 Javascript
JS实现网页游戏中滑块响应鼠标点击移动效果
2015/10/19 Javascript
Javascript打印局部页面实例
2016/06/21 Javascript
javascript运算符——逻辑运算符全面解析
2016/06/27 Javascript
详解基于vue-router的动态权限控制实现方案
2017/09/28 Javascript
vue通信方式EventBus的实现代码详解
2019/06/10 Javascript
Python脚本判断 Linux 是否运行在虚拟机上
2015/04/25 Python
Python自动化开发学习之三级菜单制作
2017/07/14 Python
python中模块查找的原理与方法详解
2017/08/11 Python
flask使用session保存登录状态及拦截未登录请求代码
2018/01/19 Python
浅谈python中requests模块导入的问题
2018/05/18 Python
python读写csv文件实例代码
2019/07/05 Python
Django获取应用下的所有models的例子
2019/08/30 Python
Html5实现移动端、PC端 刮刮卡效果
2016/06/30 HTML / CSS
GNC健安喜美国官网:美国第一营养品牌
2016/07/22 全球购物
方太官方网上商城:销售方太抽油烟机、燃气灶、消毒柜等
2017/01/17 全球购物
Hunter Boots美国官方网站:赫特威灵顿雨靴
2018/06/16 全球购物
留学推荐信怎么写
2014/01/25 职场文书
我爱读书演讲稿
2014/05/07 职场文书
婚纱店策划方案
2014/05/22 职场文书
党员学习正风肃纪思想汇报
2014/09/12 职场文书
教师调动申请报告
2015/05/18 职场文书
如何制作自己的原生JavaScript路由
2021/05/05 Javascript
PyMongo 查询数据的实现
2021/06/28 Python
使用Springboot实现健身房管理系统
2021/07/01 Java/Android
SQL Server中锁的用法
2022/05/20 SQL Server
使用 Koa + TS + ESLlint 搭建node服务器的过程详解
2022/05/30 NodeJs