原文: http://pij.robinqu.me/JavaScript_Core/JavaScript_Basics/Strict_Mode.htmlphp
本文上一个版本盗用了别人的文章,经读者指出后我就删掉了。因为起草的时间在去年,我也不太清楚当初是怎么把别人的文章复制进来的。本文除了介绍所谓的Strict Mode以外,还会介绍其余关联内容。node
JavaScript并非一个完美的语言。事实上,第一个版本的Brendan Eich1花费十天的时间创造的,你不能对它指望太多。以后,JavaScript在浏览器大战中,成为各方角逐的主要战场。各大厂商各显神通,其反作用是各类奇奇怪怪的行为和各式不一的API。在以后,W3C和其余社区团体花费了大量的精力来经过标准化来“净化”全部Web开发相关的技术标准。git
但尴尬的是,浏览器厂商并非那么彻底的实现了W3C和ECMAScript的各类标准。最后,经验丰富的Javascript程序员,经过约束自身对Javascript的使用方法,来达到让Javascript更高的可拥度。可能大部分人都读过《JavaScript语言精粹》2这本书,其讲述的就是如何在JavaScript语言中,取其精华,而后去其糟粕。程序员
而JavaScript的严格模式,则是另外一种紧箍咒,它的约束力来自运行时自己,而不是用户的主观行为。也就是说,有不少模棱两可,或是错误却被容许的操做,被完全禁止了。目前支持严格模式的支持范围3从IE10起跳,其余常青浏览器也都是支持的。github
开启全局模式只需在全部语句以前放置"use strict"
字符串常量。web
全局开启严格模式:浏览器
"use strict" var v = "Hello world";
但注意,这样会致使整个脚本内的代码都在严格模式中执行。假如以前有些代码并无考虑严格模式,这可能让你的整个应用程序忽然失效。app
咱们更为推荐的是,在某个函数内开启严格模式:ecmascript
function mySuperMethod() { "use strict"; var v = "Hello world"; } function mySuckingMethod { //not in strict mode }
你们有须要记住一堆语言特性了。可是,还好这些内容是把“歪”的掰“直”了。有少数代码例子来自于MDC4。
ReferenceError
试图隐式建立全局变量
``` "use strict" hello = "world"//throw ```
TypeError
试图修改已经被定义为不可写的属性
``` "use strict"; var o = {}; Object.defineProperty(o, "hello", {value:"world", wrtiable:false}); o.hello = "bad boy";//throw ```
其余相似的还有:
试图删除不可删除的属性
``` "use strict"; delete Object.prototype; //throw ```
arguments.callee
不能被返回、删除、修改;
``` "use strict"; var fun = function() { return arugments.callee;//throw }; ```
SyntaxError
重复定义属性名
``` "use strict"; var o = {hello: 1, hello: 2};//throw ```
禁用八进制字面量
``` "use strict"; var hello = 015;//throw ```
不容许重复参数名
``` function myMethod(a, b, b) {//throw "use strict"; } ```
不能使用with
``` "use strict"; var obj = {}; with (obj) {};//throw ```
不容许对eval
或arguments
赋值
``` var fun = function(){ "use strict"; eval=16 }(); ```
不可将eval
或arguments
做为参数名、变量名
``` var fun = function(){ "use strict"; var obj = { set p(arguments) {} }; }(); ```
eval
被限制在临时的本地做用域eval再也不有权限直接修改其所在做用于,而只能影响自身建立的做用域。
var hello = "world"; var evalHello = eval("'use strict'; var hello = "girl"; hello"); // hello === "world" // evalHello === "girl"
arguments
再也不追踪实际参数值变化function f(hello) { "use strict"; hello = "girl"; return [hello, arguments[0]]; } var pair = f("world"); // pair[0] === "girl" // pair[1] === "world";
this
不作任何修改null
或undefined
,引擎也不会从新指定全局对象做为this
"use strict"; function fun() { return this; } // fun() === undefined // fun.call(2) === 2 // fun.apply(null) === null // fun.call(undefined) === undefined // fun.bind(true)() === true
以往,咱们能够经过函数的caller
和arguments
来投影整个调用堆栈。可是,在严格模式中咱们作不到。
function restricted() { "use strict"; restricted.caller; // throws a TypeError restricted.arguments; // throws a TypeError }
implements, interface, let, package, private, protected, public, static, yield
不少开发者喜欢以下代码风格,这在严格模式中会报错。
function foo() { "use strict"; return g; function g() { }//throw SyntaxError }
这个改变的缘由是,JavaScript的Hoisting
特性会让不少人迷惑:
function g() { } function foo() { if (true) function g() { } return g; }
ES6 Draft中引入了一个新的概念5,叫Extend Mode
,而后又被撤销了6。但不幸的是,V8中已经支持了这个新模式。因此,做为事实标准,目前依赖V8的全部Javascript运行环境都有以下三个模式:
这个模式是备受争议的。这个模式的产生,也体会出制做一个标准的困难之处——你总要考虑新标准对老标准的兼容,尤为是Web技术。
有稍微了解ES6的同窗都应该清楚,module
、class
这些东西已经彻底颠覆了传统JavaScript的不少尝试。但也有很多东西,开发者是能够接受,并立马去尝试的。因而乎,关于如何让代码部分进入extended mode
也就成了最初讨论的重点7。
实际表现上,node的0.11.x的版本,有些特性,仅仅使用--harmony
并不能彻底使用,还需加上--use_strict
。在这里,已经能够看出V8团队有多纠结了8。他们也没有想清楚,该如何进入extended mode
,索性,也叫strict
吧。
目前仅在extended mode
下可用的ES6特性:
关于ES6的特性,请参考本书的相关章节。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Strict_mode ↩
http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts ↩
http://wiki.ecmascript.org/lib/exe/fetch.php?id=harmony%3Aspecification_drafts&cache=cache&media=harmony:working_draft_ecma-262_edition_6_11-7-11.pdf ↩
https://lists.webkit.org/pipermail/webkit-dev/2011-December/018903.html ↩