谈谈 JS 中的严格模式

什么是严格模式?

严格模式 是 ECMAScript 5 中引入的一种将更好的错误检查引入代码中的方法, 如今已经被大多浏览器实现. 顾名思义,这种模式使得Javascript在更严格的条件下运行.chrome

所以, 在严格模式下, 咱们的一些不严谨的写法将会致使程序抛出错误. 例如:浏览器

function fn(param) {
    var arguments = []; // 在严格模式下该行将会抛出错误: error: redefinition of arguments
}

在上面的代码中, 因为 arguments 在 js 中是一个特殊对象, 在严格模式下是不容许被从新定义的. 可是没有实现严格模式检查的环境中会接受这段代码.安全

为何会出现严格模式?

总所周知, 从 ECMAscript 从1997年正式成为国际标准以来, 已经发布了6个版本. 除此以外, 还存在一些 Javascript 实现支持非标准特性, 而其余的 Javascript 实现却并不支持这些特性的状况. 因为 Javascript 的实现多样化, 咱们很难肯定哪些特性在哪些平台上是支持的, 再加上 Web 浏览器的复杂性, 而且它并不能让开发者指定某一个特定的 Javascript 版原本执行咱们的程序. 所以咱们须要精心的编写程序, 以确保在全部的平台上都可以正常运行.性能优化

所以在 ES5 中引入了一种版本控制的考量: 严格模式. 此特性容许开发者选择在受限制的 Javascript 版本中禁止使用一些 Javascript 语言中问题较多或是易于出错的特性.函数

因为其语法强大的向后兼容特性, 因此即便在没有实现严格模式检查的环境中, 你的严格代码仍然能够正常执行.工具

如何使用严格模式?

在程序中使用严格模式的方式是在程序中的最开始增长一个特定的字符串字面量.性能

"use strict"

若是你在一个文件的顶部加入这个特定的字符串, 则表示该文件的全部内容将始终使用严格模式执行.测试

若是你只想在一个函数体内使用严格模式, 则在该函数体内的最开始处(顶部)加入这句指令.优化

为何要使用字符串字面量来实现严格模式?

单独使用一个特定的字符串字面量来做为指令语法在语言里看起来确实至关怪异, 可是他有一个最大的好处是向后兼容. 咱们来看一下它为何可以向后兼容. 咱们都知道在js 中解释执行一个字符串字面量是没有任何反作用的, 这句话什么意思呢? 好比说你在 chrome 浏览器控制台里面输入一个字符串字面量, 解释器只会返回一个一样的字符串, 除此以外不会发生任何事情, 这就使得即便ES3引擎不支持严格模式, 但依然可以无伤大雅的解释和执行这条指令. ES3 引擎在解析完改字符串以后, 会当即将该值丢弃. 所以, 尽管旧的引擎不支持严格模式, 但依然可以正常运行.版本控制

但须要注意的是: 尽管不会抛出错误, 可是旧的引擎不会进行任何的严格检查模式, 所以若是要使用严格模式, 你应该老是在彻底兼容ES5的环境中测试严格代码.

使用严格模式须要注意哪些问题?

咱们在上面已经说过, use strict 指令须要写在脚本或者函数的顶部, 由于该指令只有在写在顶部才能生效. 这就使得咱们在使用的时候须要注意一下这里有个小坑. 这个坑是什么呢?

举个例子, 咱们在开发大型功能的时候, 开发过程当中会使用多个独立的脚本文件, 可是在部署到生产环境的时候出于性能优化的目的, 须要将多个脚本链接成一个单一的文件. 好比说, 脚本1 运行于严格模式下,

// file1.js 
"use strict"
function doSth() {
}

可是有另一个同事写了一个脚本2运行于非严格模式下:

// file2.js
function doOtherSth(param) {
    var arguments = [];
}

那么, 咱们该怎么链接这两个文件呢? 若是咱们以 file1.js 开始, 那么链接后的代码将运行于严格模式下, 可是因为 file2 中的一些操做会在严格模式下抛出错误, 致使咱们的程序没法正常运行.若是咱们以 file2.js 开始, 那么链接后的代码将运行于非严格模式下, 由于咱们前面已经讲过该指令只有在写在顶部才能生效. 彷佛怎样都不太合适.

那么如何解决这个问题呢?

  1. 在项目中坚持只使用严格模式或者只使用非严格模式, 而且不要将使用严格模式和不使用严格模式的文件进行打包构建. O(∩_∩)O哈哈~这样就不会有问题了嘛.

  2. 咱们上面说过, 若是你只想在一个函数体内使用严格模式, 则在该函数体内的最开始处(顶部)加入这句指令. 咱们能够利用这个特性, 将每个脚本文件里面的代码包裹在一个当即执行的函数表达式内, 这样即便两种模式的文件打包在一块儿, 依然可以按照咱们的指望进行工做. 例如:

;(function() {
    // file1.js 
    "use strict"
    function doSth() {
    }
})();

;(function() {
    // file2.js 
    function doOtherSth() {
    }
})();

固然了, 上面这样的作法会致使这些文件的内容不会在全局做用域内解释, 这就致使咱们经过 varfunction 声明的变量不会视为全局变量. 不过这恰好对咱们来讲也是一个很好的特性. 所以就放心大胆的使用吧, 去吧, 皮卡丘.

最佳实践

上面的方法2看起来是极好的, 而且咱们能够经过自动化构建工具为咱们的脚本文件上添加如上代码. 可是若是咱们想要编写一个通用的库, 使其能够在尽量多的环境中正常工做, 咱们不能假设脚本文件必定会被构建工具置于一个当即执行的函数中, 也不能假设客户端代码必定处于严格模式或是非严格模式中. 因此为了得到最佳效果, 咱们应该老是在严格模式下编写代码, 并显式的将其包裹在启用了严格模式的当即执行函数中, 而不是依靠构建工具来实现.

结语

"严格模式"体现了Javascript更合理、更安全、更严谨的发展方向. 为了达到更为广泛的兼容性, 咱们应该老是在严格模式下编写代码.

相关文章
相关标签/搜索