理解javascript中的严格模式

一、什么是严格模式
我们平时写的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的控制台中执行,正常情况下应该报错,但是并没有报错,

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

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

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

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

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

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

时间: 2016-01-31

JavaScript起点(严格模式深度了解)

严格模式(Strict Mode)是ECMAScript5新增的功能.ECMAScript5虽然可以向后兼容ECMAScript3,但如果使用严格模式,哪些ECMAScript5"不在建议使用"的ECMAScript3语法功能将会被全部进制,如果出现就会抛出一行.引入Strict Mode目的是允许开发人员能够选择"更好"的Javascript版本,这个版本能用不同的方式处理那些普遍而又臭名昭著的错误.目前所有的主流浏览器的最新版本--包括IE10与Opera12-

老生常谈 js中this的指向

在js中this的指向对于新手来说一定是个难题,但是如果你真正理解了的话,也就没什么问题啦,下面就来讲讲this吧. JS中,this的值取决于调用的模式(调用对象),而JS中共有4种调用模式: 1.函数调用模式 当一个函数不是一个对象的属性时,当作函数俩调用,这时函数内的this指向全局对象(大对数情况下是window) window.value=1; function getValue(){ console.log(this.value); } getValue();//输出1,此时的thi

Javascript的严格模式strict mode详细介绍

"严格模式"(strict mode)是ECMA-262 Edition 5定义的新语法,表示要用严格的Javascript语法来执行,有一些过去惯用的写法就会抛出SyntaxError异常,例如:1.变量前没有用var宣告2.使用八进制语法:var n = 023和var s = "\047"3.使用with语句4.使用delete删除一个变量名(而不是属性名):delete myVariable5.使用eval或arguments作为变量名或函数名6.使用未来保

深入理解js函数的作用域与this指向

函数的作用域与this指向是js中很重要的一部分,理清这点东西需要个逻辑,看看我的逻辑怎么样... 下面是个提纲,可以直接挑你感兴趣的条目阅读. • 函数的定义方式:直接定义(window下,内部定义),对象的方法,对象原型的方法: • 函数的调用方式:直接调用,call/apply,with • 对于直接定义的函数和对象的方法,作用域默认状态下是它的定义处的作用域链. • 对于直接定义的函数,this指向window. • 对于对象的方法,this指向实例化对象(对应于实例化对象默认返回thi

js严格模式总结(分享)

首页,我们要理解严格模式的概念,严格模式是一种特殊的执行模式,它修复了部分语言上的不足,提供更强的错误检查,病增强安全性.可以对部分函数进行执行严格模式,如: function func(){ 'use strict' } 也可以对整个js文件进行执行严格模式,如: 'use strict' function func(){ } 那么我们在以下情况不能使用: 1.不允许用width 2.不允许未声明的变量被赋值 3.arguments变为参数的静态副本 4.delete参数.函数名报错 5.de

JavaScript严格模式下关于this的几种指向详解

前言 相信不少人在学习或者使用Javascript的时候,都曾经被 JavaScript 中的 this 弄晕了,那么本文就来整理总结一下在严格模式下 this 的几种指向. 一.全局作用域中的this 在严格模式下,在全局作用域中,this指向window对象 "use strict"; console.log("严格模式"); console.log("在全局作用域中的this"); console.log("this.docume

灵活的理解JavaScript中的this指向

this是JavaScript中的关键字之一,在编写程序的时候经常会用到,正确的理解和使用关键字this尤为重要.首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然网上大部分的文章都是这样说的,虽然在很多情况下那样去理解不会出什么问题,但是实际上那样理解是不准确的,所以在你理解this的时候会有种琢磨不透的感觉),那么接下来我会深入的探讨这个问题.

聊一聊JS中this的指向问题

JS中的this指向一直是个让人头疼的问题,想当初我学的是天昏地暗,查了好多资料,看的头都大了,跟他大战了那么多回合,终于把它搞定个七八分,其实往往都是我们复杂化了,现在就让大家轻松看懂this的指向,我会分以下几种情况来说. this的指向: 1.this 指的是调用当前方法(函数)的那个对象,也就是说函数在谁那被调用,this就指的是谁. 来看两个栗子: oBtn.onclick = function(){ alert(this); //oBtn } oBtn[i].onclick = fn

JS中改变this指向的方法(call和apply、bind)

this是javascript的一个关键字,随着函数使用场合不同,this的值会发生变化.但是总有一个原则,那就是this指的是调用函数的那个对象. this一般指向的是当前被调用者,但也可以通过其它方式来改变它的指向,下面将介绍三种方式: 1.call用作继承时: function Parent(age){ this.name=['mike','jack','smith']; this.age=age; } function Child(age){ Parent.call(this,age);

JS中this的指向以及call、apply的作用

在具体的实际应用中,this 的指向无法在函数定义时确定,而是在函数执行的时候才确定的,根据执行时的环境大致可以分为以下3种: 1.当函数作为普通函数调用时,this 指向全局对象 2.当函数作为对象的方法调用时,this 指向该对象 3.当函数作为构造器调用时,this 指向新创建的对象 示例一: window.name = 'myname'; function getName() { console.log(this.name); } getName(); //输出myname 示例二: v

聊一聊JS中的prototype

什么是prototype: function定义的对象有一个prototype属性,prototype属性又指向了一个prototype对象,注意prototype属性与prototype对象是两个不同的东西,要注意区别.在prototype对象中又有一个constructor属性,这个constructor属性同样指向一个constructor对象,而这个constructor对象恰恰就是这个function函数本身. //判断是否是数组 function isArray(obj) { ret

js中this的指向问题归纳总结

前言 js中this指向问题是个老生常谈的问题了,下面这篇文章再来给大家介绍下,大家可以看看,更深入的了解了解,下面话不多说了,来一起看看详细的介绍吧 this this:上下文,会根据执行环境变化而发生指向的改变. 1.单独的this,指向的是window这个对象 alert(this); // this -> window 2.全局函数中的this function demo() { alert(this); // this -> window } demo(); 在严格模式下,this是

Angular.JS中的this指向详解

[this详解] 1.谁最终调用函数,this指向谁. ① this指向的,永远只可能是对象!!!!!! ② this指向谁,永远不取决于this写在哪!!而是取决于函数在哪调用. ③ this指向的对象,我们称之为函数的上下文context,也叫函数的调用者 2.※※※※※this指向的规律(与函数调用的方式息息相关): this指向的情况,取决于函数调用的方式有哪些: ① 通过函数名()直接调用:this指向window ② 通过对象.函数名()调用的:this指向这个对象 ③ 函数作为数组

关于JavaScript中的this指向问题总结篇

在javascript中this的指向一直是前端同事的心头病,也同时是各面试题的首选,现在我们就来总结一下js中this的指向.首先需要了解一下几个概念: 1:全局变量默认挂载在window对象下 2:一般情况下this指向它的调用者 3:es6的箭头函数中,this指向创建者,并非调用者 4:通过call.apply.bind可以改改变this的指向 下面我们具体分析一下 1:在函数调用时 (非严格模式) const func = function () { console.log(this)

js中apply和Math.max()函数的问题及区别介绍

下面给大家介绍js中apply和Math.max()函数的问题,具体内容如下所示: var arr=[1,3,6,3,7,9,2]; console.log(Math.max.apply(null,arr)); 一直搞不懂为什么这样可以算出一个数组的最大值?一直想不明白,请js高手指教一下. 答案1 Function.apply()是JS的一个OOP特性,一般用来模拟继承和扩展this的用途,对于上面这段代码,可以这样去理解: XXX.apply是一个调用函数的方法,其参数为:apply(Fun

浅谈JS中this在各个场景下的指向

为了保证的可读性,本文采用意译而非直译. 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! 1. this 的奥秘 很多时候, JS 中的 this 对于咱们的初学者很容易产生困惑不解. this 的功能很强大,但需要一定付出才能慢慢理解它. 对Java.PHP或其他标准语言来看,this 表示类方法中当前对象的实例.大多数情况下,this 不能在方法之外使用,这样就比较不会造成混淆. 在J要中情况就有所不同: this表示函数的当前执行上下文,JS 中函数调用主要有以下几种