js的严格模式

745 阅读3分钟

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

严格模式解析

严格模式(Strict mode)是由ECMA-262规范定义的新兴JavaScript标准,发布于2009年12月第五版。也就是在es5中添加的。旨在改善错误检查功能并且标识可能不会延续到未来JavaScript版本的脚本。ES5严格模式是限制性更强的JavaScript变体,它与常规JavaScript的语义不同,其分析更为严格。

了解严格模式缘由

在一次会上,我们讲到尾调用的优化时,有一句话是这样的:ES6 的尾调用优化只在严格模式下开启,正常模式是无效的。这是因为在正常模式下,函数内部有两个变量,可以跟踪函数的调用栈。

  • func.arguments:返回调用时函数的参数。
  • func.caller:返回调用当前函数的那个函数。

尾调用优化发生时,函数的调用栈会改写,因此上面两个变量就会失真。严格模式禁用这两个变量,所以尾调用模式仅在严格模式下生效。

function restricted() {
  'use strict';
  restricted.caller;    // 报错
  restricted.arguments; // 报错
}
restricted();

这个时候,我就问了一下同事,咋们的项目不是严格模式的吗?同事说不是。我就觉得不太对吧,我看咋们写代码应该都是有提示,不给使用一些正常模式下的语法的吧。就像上面的arguments

然后,我就去了解了一下怎么算是严格模式。

开启严格模式

ECMAScript的2015年语言规范中写到

Global code is strict mode code if it begins with a Directive Prologue that contains a Use Strict Directive(如果全局代码以包含使用严格指令的指令序言开头,则它是严格模式代码)
'use strict' is unnecessary inside of modules (模块内部不需要“严格使用”)
ArrowFunction is contained in strict mode code or if the code that produces the value of the function’s [[ECMAScriptCode]] internal slot begins with a Directive Prologue that contains a Use Strict Directive产生函数 [[ECMAScriptCode]](内部槽值的代码以指令序言开头,则函数代码是严格模式代码包含使用严格指令)

相当于下面这些情况:

全局

'use strict';

function doSomething(a, b = a) {
  // code
}

es模块

现代浏览器支持ES模块,但有一些警告。 要使用模块,需要在 script 标签上添加属性 type, 对应值 为 module

局部


function doSomething(a, b) {
  'use strict';
  // code
}

严格模式的限制

ecmascript6入门中写道
严格模式主要有以下限制。

  • 变量必须声明后再使用
  • 函数的参数不能有同名属性,否则报错
  • 不能使用with语句
  • 不能对只读属性赋值,否则报错
  • 不能使用前缀 0 表示八进制数,否则报错
  • 不能删除不可删除的属性,否则报错
  • 不能删除变量delete prop,会报错,只能删除属性delete global[prop]
  • eval不会在它的外层作用域引入变量
  • evalarguments不能被重新赋值
  • arguments不会自动反映函数参数的变化
  • 不能使用arguments.callee
  • 不能使用arguments.caller
  • 禁止this指向全局对象
  • 不能使用fn.callerfn.arguments获取函数调用的堆栈
  • 增加了保留字(比如protectedstaticinterface

在我们项目中,我输入了'use strict'; 出现了下面的警告

image.png 然后在eslint上也看到了这个配置

image.png

可以看到,"sourceType": "module", //指定源代码存在的位置,script | module,默认为script。应该算是代表我们的项目开启了模块化了吧,毕竟写代码的时候都有模块化的校验。