JavsScript严格模式

严格模式

严格模式(strict mode):使 JavaScript 代码在更加严格的条件下运行。
严格模式不仅仅是一个子集,它故意(人为)设置与标准模式不同的语义。就是说,相同的代码在严格模式和标准模式下可能会有不同的行为表现。

如何开启严格模式?

1. 针对整个脚本文件的严格模式

在 script 标签下的第一行使用 "use strict";代码开启严格模式。
若这行语句不是在第一行运行,那么脚本依然还是会使用“标准模式”运行。
示例:

    <script>
        // 针对脚本文件开启严格模式,整个文件会以严格模式运行
        "use strict";
    </script>

针对整个脚本文件的严格模式在文件合并时会出现冲突,比如严格模式和非严格模式的文件合并会出现冲突,导致运行错误。同样模式的文件合并不会出现这个问题,谨慎使用这个方式的严格模式。

2. 针对某个函数作用域的严格模式

在声明函数的时候,在函数体的第一行使用"use strict";开启严格模式。
示例:

function fn(){
  "use strict";
  // 这个函数将会以严格模式调用
}

3. 折中的全局严格模式

由于第一种方法的严格模式存在文件合并冲突的问题,可以结合第二种方法进行折中的处理。
方法如下:

将整个文件的 JavaScript 代码包装到一个函数之中,在该函数中开启严格模式。使用这些 JavaScript 代码的方式就是调用这个函数,这样就可以间接地达到严格模式的要求,而又不会有文件合并冲突。

严格模式与标准模式的不同

1. 不允许隐式声明变量

在标准模式中,若在a = '字符串'执行之前变量 a 没有被声明,那么JS引擎会自动在全局作用域之中隐式声明一个全局变量 a。
在严格模式中,类似a = '字符串'的操作将会直接报错,声明变量必须显式使用关键字(var、let等)声明。

    <script>
        "use strict";
        a = '字符串';   //Uncaught ReferenceError: a is not defined
    </script>

这个特性可以避免某些情况下拼错变量名而造成的新增全局变量,影响后续代码运行的情况发生。

2. 严格模式会使标准模式下静默失败的代码报错

静默失败:代码执行失败,不报错。

常见的静默失败:

  • 给对象不可写属性赋值
  • 给对象只读属性赋值
  • 给不可扩展对象的新属性赋值
  • 删除对象中不可删除的属性

这些静默失败在标准模式下全部不会报错。而在严格模式下:

<script>
    "use strict";
    // 给不可写属性赋值
    var obj1 = {}
    Object.defineProperty(obj1,'x',{value:'我是obj1.x的值',writable:false}) // 给obj1设置一个x属性,值为'我是obj1.x的值',且设置为不可写属性
    console.log(obj1.x)         // 我是obj1.x的值
    obj1.x = 9                  // Uncaught TypeError: Cannot assign to read only property 'x' of object '#<Object>'

    // 给只读属性赋值
    var obj2 = { get x() {return 22;}} // 声明对象obj2,且给该对象设置一个值为22的只读属性 x
    console.log(obj2.x)               // 22
    obj2.x = 9                        // Uncaught TypeError: Cannot set property x of #<Object> which has only a getter 

    // 给不可扩展对象的新属性赋值
    var obj3 = {}  // 声明新对象 obj3
    Object.preventExtensions(obj3)  // 将 obj3 设置为不可扩展对象 
    obj3.newProp = "aaa"            // Uncaught TypeError: Cannot add property newProp, object is not extensible

    // 删除对象的不可删除属性
    delete Object.prototype        // Uncaught TypeError: Cannot delete property 'prototype' of function Object() { [native code] }
</script>

3. 重名的错误

1. 对象属性名重复

标准模式下,允许对象的属性名重复而不报错,但是对象之中只会有后面的那个属性(后面的属性覆盖前面的属性)。

<script>
    var a = {
        a : "aaa",
        a : "bbb"
    }
    console.log(a)  // {a: "bbb"}
</script>

而在严格模式下,对象属性名重复会报错(ES 6已经不报错,所以在ES 6的严格模式中,对象属性名重复和正常模式一样 )。

<script>
    "use strict";
    var a = {
        a : "abb",
        a : "bbb"
    };  // 语法错误(我用的是支持ES 6的 Chrome 浏览器,所以不报错了。。。)
</script>
2. 函数形参名重复

标准模式下,函数形参名重复,最后的那一个形参会覆盖前面的同名形参,即只有后一个生效。参数依然可以使用伪数组 arguments[i] 来获取

function fn(a,a,b){
    return a + b;
}
fn(1,2,3)         // 5

严格模式下,函数形参名规定是唯一的,重负将会报错

function fn(a,a,b){
    "use strict";
    return a + b;
}
fn(1,2,3)  // Uncaught SyntaxError: Duplicate parameter name not allowed in this context

4. 严格模式禁止八进制语法

标准模式下,数字前缀为 0 ,JS引擎会自动默认为八进制数。

var a = 010,
    b = 011,
    c = 020;
console.log(a)    // 8
console.log(b)    // 9
console.log(c)    // 16

严格模式下,不支持八进制语法,将会报错。

"use strict";
var a = 010,
    b = 011,
    c = 020;
// 报错:Uncaught SyntaxError: Octal literals are not allowed in strict mode.

5. 严格模式禁止设置简单类型(number、string、symbol、boolean、null、undefined)的属性

标准模式下,给简单类型设置属性不会报错

(14).sailing = "home"; 
console.log((14).sailing = "home")     // home 

严格模式下,给简单类型设置属性会报错

"use strict";
(14).sailing = "home"; 
console.log((14).sailing = "home") 
// 报错:Uncaught TypeError: Cannot create property 'sailing' on number '14'

6. 严格模式禁止删除变量

标准模式下,使用delete关键字删除变量虽然不能删除成功,但是也不会报错

var x = 11;
delete x;
console.log(x)   // 11

严格模式下,直接报错。

"use strict";
var x = 11;
delete x;
console.log(x)
// 报错:Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.

不知道这种差别属不属于静默失败的范围,有知道的同学请给我留言,谢谢。

7. 静态绑定

严格模式只允许静态绑定属性和方法,即在编译时就确定方法和属性属于哪个对象。

1. 禁止使用 with 语句

with 语句有一个众所周知的缺陷——无法准确确定对象。所以,严格模式下,是不允许使用with语句的。

2. 创设eval作用域

标准模式下,ES 6 之前的JavaScript 只有全局作用域函数作用域两种作用域,而严格模式下,eval函数也可以创设一个作用域,该作用域只在eval函数中有效。

"use strict";
var x = 11;
eval("var x = 2;console.log(x)")  // 2
console.log(x)                    // 11

8. 严格模式禁止 this 指向全局对象

严格模式下,this 禁止指向全局对象。
标准模式下,调用函数,函数中的 this指向全局对象

function f(){
    console.log(this)
}
f() // 打印出 Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}

严格模式下,this指向undefined

function f(){
    "use strict";
    console.log(this);
}
f();  // undefined

9. 对 arguments 的限制

1. 不允许对 arguments 赋值

标准模式下,允许对arguments进行赋值

function f(){
    arguments = 1
    console.log(arguments)
}
f(1,2,3);  // 1

严格模式下,报错。

function f(){
    "use strict";
    arguments = 1
    console.log(arguments)
}
f(1,2,3); // Uncaught SyntaxError: Unexpected eval or arguments in strict mode
2. 严格模式下,arguments不再追踪参数的变化

标准模式

function f(a){
    a = 1
    console.log(a)
}
f(5);  // 1

严格模式

function f(a) {
  a = 2;
  return [a, arguments[0]];
}
f(1); // 正常模式为[2,2]

function f(a) {
  "use strict";
  a = 2;
  return [a, arguments[0]];
}
f(1); // 严格模式为[2,1]
3. 禁止使用arguments.callee

arguments.callee => 调用当前匿名函数的函数体(再执行一次)
也就是说,无法在匿名函数中调用自身了

"use strict";
var f = function(){ return arguments.callee}
f(); 
// 报错:Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

总结

  • 严格模式不允许隐式声明变量
  • 严格模式会使标准模式下静默失败的代码报错
  • 严格模式不允许函数形参名重复
  • 严格模式禁止八进制语法
  • 严格模式禁止设置简单类型(number、string、symbol、boolean、null、undefined)的属性
  • 严格模式禁止删除变量
  • 严格模式静态绑定属性和方法(禁止使用witheval作用域)
  • 严格模式下的this指向undefined(未指定)
  • 严格模式对arguments对象的限制(不允许赋值、不追踪参数变化、禁止argument.callee,匿名函数无法调用自身)

参考链接

Javascript 严格模式详解
严格模式 | MDN

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

推荐阅读更多精彩内容

  • 那一年参加完妹妹的婚礼,第二天早晨,一边听着车外鸟儿清脆的叫声,一边细数着心中无比的感动…… 原本不再属于我的暑假...
    天涯草阅读 329评论 0 0
  • 鼓励与自由书写第5天 关于上方卡的活动真的特别好玩,每听一次课感受都不同,我一共听了两次,和女儿玩了两次,然后对生...
    中湉妈妈与正面管教阅读 569评论 0 1
  • 凉风轻抚,城市的燥热尽散,湛蓝天空白云朵朵,有大智慧的人说,未来是人类能量大提升的新纪元,如果我们不能了悟世界运作...
    花开见佛笑阅读 172评论 0 1
  • -2014年5月某某号-二零零六年上下,城里人甚至没有“小区”的概念,正经住户的住房,一栋一栋像坏牙一样极不规整地...
    80bc5dc07a4a阅读 311评论 0 0