javascript的严格模式与有什么特点?

1,546 阅读4分钟

JavaScript 除了提供正常模式外,还提供了严格模式(strict mode)。ES5 的严格模式是采用具有限制性 JavaScript变体的一种方式,即在严格的条件下运行 JS 代码。 严格模式在 IE10 以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。

严格模式对正常的 JavaScript 语义做了一些更改:

  1. 通过抛出错误消除原有的静默错误,eg, 未定义使用变量,undifined
  2. 修复了一些导致javascript引擎难以执行优化的缺陷:有时候,相同的代码,严格模式可以比非严格模式下运行更快
  3. 禁用了在 ECMAScript 的未来版本中可能会定义的一些语法。比如一些保留字如:class,enum,export, extends, import, super 不能做变量名

开启严格模式

严格模式可以应用到整个脚本或个别函数中。因此,可以将严格模式分为为脚本开启严格模式为函数开启严格模式两种情况。

为脚本开启严格模式

use strict放在第一行,则整个脚本以严格模式运行。如果不在第一行,则无效。当不同模式的代码文件合并时,需要特别注意。
有的 script 脚本是严格模式,有的 script 脚本是正常模式,这样不利于文件合并,可以将整个脚本文件放在一个立即执行的匿名函数之中。这样独立创建一个作用域而不影响其他script 脚本文件。

<script>
   "use strict"; //当前script标签开启了严格模式
    console.log("it's strict mode")
</script>
<script>
    console.log("it's non-strict mode")//当前script标签未开启严格模式
</script>
// 脚本的变通写法,在一个js文件中,将代码写在一个IIFE中
(function(){
      'use strict'
      // write code here
 })()

为函数开启严格模式

要给某个函数开启严格模式,需要把“use strict”; (或 'use strict'; ) 声明放在函数体所有语句之前。

//当前fn函数开启了严格模式
function fn(){
  "use strict";
  return "123";
} 

严格模式中的变化

1. 全局变量显示声明

'use strict'
num = 10 
console.log(num) // 报错,num未声明

2. 静态绑定

(1) 禁止使用with语句

function f(x, o) {
  with(o) {
    console.log(x)
  }
}
f(null, {x:3}) // 3
// with 语句 
// 弊端:代码不易阅读,易混淆,程序在查找变量值时,先从指定的对象里找,那些不是指定对象的变量查找起来会很慢。
// 优点:减少不必要的指针路径解析运算

(2) 创设eval作用域

严格模式创设额外的作用域,正常模式下,eval作用域取决于它处于全局作用域还是函数作用域。严格模式下,eval语句本身就是一个作用域,不再生成全局变量,生成的变量只能用于eval内部。

'use strict'
var x = 2
console.info(eval('var x = 5; x')) // 5,  将计算js字符串,将其作为脚本代码来执行
console.log(x)  //  2

3. 增强的安全措施

(1) 禁止this指向全局对象(定时器的this还是指向window)

function Star() {
     this.sex = '男';
}
Star();  // 4. 严格模式下,如果构造函数不加new调用, this 指向undefined, 赋值则会报错.
var ldh = new Star();
console.log(ldh.sex);

(2) 禁止在函数内部遍历调用栈

function fn() {
  'use strict'
  fn.caller  // 报错------返回调用fn的作用域所属的函数,window为null
  fn.arguments  // 报错
}
fn()

4. 禁止删除变量

'use strict'
var num2 = 1;
delete num2; //  报错
// 只有configurable设置为true的对象属性,才能被删除
var o = Object.create(null, {'x': {value:1, configurable: true}})
delete o.x // 删除成功

5. 显式报错

  • 正常模式下,对一个对象的只读属性进行赋值,不会报错,只会默默地失败;严格模式下会报错。
  • 严格模式下,对一个使用getter方法读取的属性进行赋值,会报错
  • 对禁止扩展的对象添加新属性
  • 删除不可删除的属性
'use strict'
var o = {}
Object.defineProperty(o, 'v', { value: 1, writable: false })
o.v = 2 // 报错 Cannot assign to read only property 'v' of object '#<Object>'
var g = {
  get a() {return 1}
}
g.a = 2 // error,   a通过get定义,是只读属性,不允许set
var e = {}
Object.perventExtensions(e)  // preventExtensions是禁止扩展函数
e.b = 1 // error
delete Object.prototype // error
6. more...

对象内重命名属性,函数参数中重名参数,禁止八进制表示法,不允许对arguments赋值,arguments不再追踪参数的变化,禁止使用arguments.callee,函数必须声明在顶层,保留字

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]

更多严格模式要求参考