1.严格模式的使用

严格模式的使用很简单,只有在代码首部加入字符串 “use strict”。有两种应用场景,一种是全局模式,一种是局部模式。

1.全局模式

  1. 'use strict'
  2. var globalVal = 100
  3. console.log(globalVal)

执行后输出100,与非严格模式没有区别

2.局部模式

讲’use strict’放入函数的第一行中

function func() {
    'use strict'
    var localVal = 200
    console.log(localVal)
}
func()

执行后输出了200,与非严格模式也没有什么区别

3.模块模式

如果你想定义一个模块或者一个小库,自然采用一个匿名函数自执行是不错的选择

function() {
    "use strict";

    // Define your library strictly...
}();

“use strict” 的位置是很讲究的,必须在首部。首部指其前面没有任何有效js代码。
以下都是无效的,将不会触发严格模式。

1.’use strict’前面有代码
var width = 10
'use strict'
globalVar = 100

2.’use strict’有两个空语句都不行
;
'use strict'
globalVar = 100

function func() {
    ;
    'use strict'
    localVar = 200
}

function func() {
    ;'use strict'
    localVar = 200
}

‘use strict’前面可以加注释
// strict mode
'use strict'
globalVar = 100

function func() {
    // strict mode
    'use strict'
    localVar = 200
}
func()

2.严格模式下的限制

1)不使用var声明变量严格模式中将不通过

我们知道JS是弱类型,宽松的语言。不使用var声明的变量默认转为全局变量。但在严格模式中将不允许,会报语法错误。

'use strict'
globalVal = 100

此时执行就会报错
image.png
全局for循环

'use strict'
for (i=0; i<5; i++) {
    console.log(i)
}

这种写法在非严格模式中很危险,i 会不小心溢出成为全局变量。但在严格模式中会报错
image.png
局部模式

function func() {
    'use strict'
    localVal = 200
    console.log(localVal)
}
func()

执行会报错
image.png
因此,严格模式中声明变量务必记得加一个var。

2)任何使用’eval’操作都会被禁止

'use strict'
var obj = {}
var eval = 3
obj.eval = 1
obj.a = eval
for (var eval in obj) {}
function eval() {}
function func(eval) {}
var func = new Function('eval')

image.png

3) eval作用域

S中作用域有两种,全局作用域和函数作用域。严格模式带来了第三种作用域:eval作用域,如下

'use strict'
var a = 10
eval('var a = 20; console.log(a)')
console.log(a)

Firebug控制台依次输出了20,10。eval是在全局模式下(非函数内)的,如果不加严格模式,此时修改的是全局的a。即输出20,20。

4) with被禁用

'use strict'
with({a:1}) {

}

image.png

5) callee和caller被禁用

function func() {
    'use strict'
    arguments.callee
    arguments.caller
}
func()

image.png

6)对禁止的对象添加新属性会报错

'use strict'
var obj = {}
Object.preventExtensions(obj)
obj.a = 1 // 报错

image.png

7) 删除系统内置的属性会报错

'use strict'
delete Object.prototype    // 报错
delete Function.prototype // 报错

image.png

等等

全局变量显式声明
静态绑定
严格模式下的执行限制
1.禁止使用 with 语句
2.eval 中定义的变量都是局部变量
禁止 this 关键字指向全局对象
禁止在函数内部遍历调用栈
严格模式下无法删除变量。只有 configurable 设置为 true 的对象属性,才能被删除。
正常模式下,对一个对象的只读属性进行赋值,不会报错,只会默默地失败。严格模式下,将报错。
严格模式下,对一个使用 getter 方法读取的属性进行赋值,会报错。
严格模式下,对禁止扩展的对象添加新属性,会报错。
严格模式下,删除一个不可删除的属性,会报错。
正常模式下,如果对象有多个重名属性,最后赋值的那个属性会覆盖前面的值。严格模式下,这属于语法错误。
正常模式下,如果函数有多个重名的参数,可以用 arguments[i]读取。严格模式下,这属于语法错误。
正常模式下,整数的第一位如果是 0,表示这是八进制数,比如 0100 等于十进制的 64。严格模式禁止这种表示法,
整数第一位为 0,将报错。
不允许对 arguments 赋值
arguments 不再追踪参数的变化
禁止使用 arguments.callee
严格模式只允许在全局作用域或函数作用域的顶层声明函数。也就是说,不允许在非函数的代码块内声明函数
严格模式新增了一些保留字:implements, interface, let, package, private, protected, public, 
  static, yield。

3.严格模式的优点

  • 使调试更加容易。那些被忽略或默默失败了的代码错误,会产生错误或抛出异常,因此尽早提醒你代码中的问题,你才能更快地指引到它们的源代码。(实时显示错误代码,方便调试)
  • 防止意外的全局变量。如果没有严格模式,将值分配给一个未声明的变量会自动创建该名称的全局变量。这是JavaScript中最常见的错误之一。在严格模式下,这样做的话会抛出错误。(如果一个变量在没声明就赋值,这个变量会自动变成全局变量,防止意外)
  • 消除 this 强制。如果没有严格模式,引用null或未定义的值到 this 值会自动强制到全局变量。这可能会导致许多令人头痛的问题和让人恨不得拔自己头发的bug。在严格模式下,引用 null或未定义的 this 值会抛出错误。
  • 不允许重复的属性名称或参数值。当检测到对象(例如,var object = {foo: “bar”, foo: “baz”};)中重复命名的属性,或检测到函数中(例如,function foo(val1, val2, val1){})重复命名的参数时,严格模式会抛出错误,因此捕捉几乎可以肯定是代码中的bug可以避免浪费大量的跟踪时间。(避免重复命名,变量,参数,等)
  • 使eval() 更安全。在严格模式和非严格模式下,eval() 的行为方式有所不同。最显而易见的是,在严格模式下,变量和声明在 eval() 语句内部的函数不会在包含范围内创建(它们会在非严格模式下的包含范围中被创建,这也是一个常见的问题源)。(eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。)
  • 在 delete使用无效时抛出错误。delete操作符(用于从对象中删除属性)不能用在对象不可配置的属性上。当试图删除一个不可配置的属性时,非严格代码将默默地失败,而严格模式将在这样的情况下抛出异常。