JS严格模式

通过严格模式,可以在函数内部 选择进行较为严格的全局或局部的错误条件检测。使用严格模式的好处是可以提早知道代码中存在的错误,及时捕获一些可能导致编程错误的ECMAScript行为。
支持严格模式的浏览器包括IE10+、Firefox 4+、Safari 5.1+和Chrome。

选择使用

要选择进入严格模式,可以使用严格模式的编译指示:

"use strict";

这种语法可以向后兼容那些不支持严格模式的JavaScript引擎。支持严格模式的引擎会启动这种模式,而不支持该模式的引擎就当遇到了一个未赋值的字符串字面量,会忽略这个编译指示。
如果是在全局作用域中(函数外部)给出这个编译指示,则整个脚本都将使用严格模式。也可以只在函数中打开严格模式:

function doSomething(){ 
    "use strict";

    //其他代码
}

变量

在严格模式下,什么时候创建变量以及怎么创建变量都是有限制的。首先,不允许意外创建全局变量。

//未声明变量 
//非严格模式:创建全局变量 
//严格模式:抛出 ReferenceError
message = "Hello world! ";

其次,不能对变量调用delete操作符。非严格模式允许这样操作,但会静默失败(返回false)。 而在严格模式下,删除变量也会导致错误。

//删除变量
//非严格模式:静默失败 
//严格模式:抛出 ReferenceError
var color = "red"; 
delete color;

严格模式下对变量名也有限制。特别地,不能使用implementsinterfaceletpackageprivateprotectedpublicstaticyield作为变量名。这些都是保留字。在严格模式下,用以上标识符作为变量名会导致语法错误。

对象

一般来说,非严格模式下会静默失败的情形,在严格模式下就会抛出错误。
在下列情形下操作对象的属性会导致错误:

  • 为只读属性赋值会抛出TypeError
  • 对不可配置的的属性使用delete操作符会抛出TypeError
  • 为不可扩展的的对象添加属性会抛出TypeError

使用对象的另一个限制与通过对象字面量声明对象有关。在使用对象字面量时,属性名必须唯一。例如:

//重名属性 
//非严格模式:没有错误,以第二个属性为准 
//严格模式:抛出语法错误
var person = { 
    name: "Nicholas", 
    name: "Greg" 
};

函数

首先,严格模式要求命名函数的参数必须唯一。

//重名参数 
//非严格模式:没有错误,只能访问第二个参数 
//严格模式:抛出语法错误
function sum (num, num){ 
    //do something
}

在非严格模式下,这个函数声明不会抛出错误。通过参数名只能访问第二个参数,要访问第一个参数必须通过arguments对象。
在严格模式下,arguments对象的行为也有所不同。在非严格模式下,修改命名参数的值也会反映到arguments对象中,而严格模式下这两个值是完全独立的。

//修改命名参数的值 
//非严格模式:修改会反映到 arguments 中 
//严格模式:修改不会反映到 arguments 中
function showValue(value){
    value = "Foo";
    alert(value);        //"Foo" 
    alert(arguments[0]); //非严格模式:"Foo" 
                         //严格模式:"Hi"
}
showValue("Hi");

在函数内部,value被改为"Foo"。在非严格模式下,这个修改也会改变arguments[0]的值,但在严格模式下,arguments[0]的值仍然是传入的值。
另一个变化是淘汰了arguments.calleearguments.caller。在非严格模式下,这两个属性一个引用函数本身,一个引用调用函数。而在严格模式下,访问哪个属性都会抛出TypeError

//访问 arguments.callee 
//非严格模式:没有问题 
//严格模式:抛出 TypeError
function factorial(num){
    if (num <= 1) {
        return 1;
    } else {
        return num * arguments.callee(num-1)
    }
}
var result=factorial(5);

类似地,尝试读写函数的caller属性,也会导致抛出TypeError。所以,对于上面的例子而言, 访问factorial.caller也会抛出错误。
与变量类似,严格模式对函数名也做出了限制,不允许用implementsinterfaceletpackageprivateprotectedpublicstaticyield作为函数名。
对函数的最后一点限制,就是只能在脚本的顶级和在函数内部声明函数。也就是说,在if语句中声明函数会导致语法错误:

//在 if 语句中声明函数 
//非严格模式:将函数提升到 if 语句外部 
//严格模式:抛出语法错误
if (true){
    function doSomething(){ 
          //...
    }
}

eval()

eval()函数在严格模式下也得到了提升。最大的变化就是它在包含上下文中不再创建变量或函数。

//使用 eval()创建变量
//非严格模式:弹出对话框显示 10
//严格模式:调用 alert(x)时会抛出 ReferenceError
function doSomething(){ 
    eval("var x=10"); 
    alert(x);
}

如果是在非严格模式下,以上代码会在函数doSomething()中创建一个局部变量x,然后alert()还会显示该变量的值。但在严格模式下,在doSomething()函数中调用eval()不会创建变量x,因此调用alert()会导致抛出ReferenceError,因为x没有定义。
可以在eval()中声明变量和函数,但这些变量或函数只能在被求值的特殊作用域中有效,随后就将被销毁。

"use strict";
var result = eval("var x=10, y=11; x+y"); 
alert(result); //21

在调用alert()时,尽管xy已经不存在了,result变量的值仍然是有效的。

eval与arguments

严格模式已经明确禁止使用evalarguments作为标识符,也不允许读写它们的值。

//把eval和arguments作为变量引用 
//非严格模式:没问题,不出错 
//严格模式:抛出语法错误
var eval = 10;
var arguments = "Hello world!";

在非严格模式下,可以重写eval,也可以给arguments赋值。但在严格模式下,这样做会导致语法错误。不能将它们用作标识符,意味着以下几种使用方式都会抛出语法错误:

  • 使用var声明;
  • 赋予另一个值;
  • 尝试修改包含的值,如使用++;
  • 用作函数名;
  • 用作命名的函数参数;
  • try-catch语句中用作例外名。

抑制this

在非严格模式下使用函数的apply()call()方法时,nullundefined值会被转换为全局对象。而在严格模式下,函数的this值始终是指定的值,无论指定的是什么值。

//访问属性
//非严格模式:访问全局属性 
//严格模式:抛出错误,因为this的值为null
var color = "red";
function displayColor(){ 
    alert(this.color);
}
displayColor.call(null);

其他变化

首先是抛弃了with语句。非严格模式下的with语句能够改变解析标识符的路径,但在严格模式下,with被简化掉了。因此,在严格模式下使用with会导致语法错误。

//with的语句用法 
//非严格模式:允许 
//严格模式:抛出语法错误
with(location){ 
    alert(href);
}

严格模式也去掉了JavaScript中的八进制字面量。以0开头的八进制字面量过去经常会导致很多错误。在严格模式下,八进制字面量已经成为无效的语法了。

//使用八进制字面量 
//非严格模式:值为 8 
//严格模式:抛出语法错误
var value = 010;

八进制字面量在严格模式下会被当作以0开头的十进制字面量。

//使用parseInt()解析八进制字面量 
//非严格模式:值为 8 
//严格模式:值为 10
var value = parseInt("010");
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容