(function () {'use strict';})()与"use strict"的区别及使用疑问
嘿,作为刚接触JavaScript的新手,能注意到这两种严格模式写法的差异已经很棒了!咱们一步步来拆解你的问题:
两种严格模式写法的核心区别
你最初的理解是对的,但还有一些细节需要补充:
- 直接在文档开头写
"use strict";:这会将整个当前脚本文件/代码块(从它出现的位置开始)切换到严格模式。如果放在文件最顶部,那整个文件里的代码都会受到严格模式规则的约束。 - 用
(function () {'use strict';})()包裹代码:这是把严格模式限制在这个自执行匿名函数的局部作用域内。如果你的全部代码都塞在这个函数里,看起来整个代码都在严格模式下,但本质上是“局部严格”——函数外部的代码(如果有的话)还是普通模式。更重要的是,这个自执行函数会创建一个独立的作用域,里面的变量、函数不会默认暴露到全局环境中。
为什么有人会用自执行函数包裹整个代码?
这种写法在ES6模块普及之前非常流行,主要有几个原因:
- 避免全局变量污染:自执行函数的局部作用域能把内部的变量、函数“隔离”起来,不会自动挂载到全局的
window对象上。比如你在函数里定义let username = "Starkemp315",外面的代码根本访问不到这个变量,不会和其他脚本的全局变量冲突。 - 兼容旧代码/第三方库:如果你的项目里混了一些不支持严格模式的老代码,或者引入的第三方库没做严格模式适配,把自己的代码放在严格模式的自执行函数里,就不会影响外部的非严格模式代码,避免出现兼容性报错。
- 逐步迁移到严格模式:在严格模式刚推出的时候,很多开发者不敢直接给整个文件开严格模式(怕老代码触发严格模式的禁止规则),所以用这种方式把新代码放在局部严格环境里,逐步替换旧代码。
为什么你测试时包裹自执行函数后代码无法运行?
最常见的原因是作用域变化导致的变量/函数访问不到,咱们举个具体的例子:
假设你原来的代码是这样的(全局严格模式下能正常运行):
"use strict"; function greet() { console.log("Hello!"); } greet(); // 正常执行,因为greet是全局函数
当你把代码包裹进自执行函数后:
(function () { 'use strict'; function greet() { console.log("Hello!"); } })(); greet(); // 报错:greet is not defined
这是因为greet现在是自执行函数内部的局部函数,外部的全局作用域根本找不到它。如果你的代码原本依赖全局变量/函数的访问,包裹后就会出现这类错误。
解决办法也很简单:如果需要让内部的变量/函数能被全局访问,可以主动挂载到window上,比如:
(function () { 'use strict'; function greet() { console.log("Hello!"); } window.greet = greet; // 把函数暴露到全局 })(); greet(); // 现在就能正常运行了
什么时候该选哪种写法?
- 选全局
"use strict";:- 你的代码是独立的新项目,没有依赖非严格模式的旧代码。
- 你使用ES6模块(比如
.mjs文件,或者在package.json里设置"type": "module")——ES6模块默认就是严格模式,甚至不用手动写"use strict"。 - 你想让整个代码都遵循严格模式的规则,减少潜在bug(比如禁止未声明变量、禁止
with语句、避免意外修改全局变量等)。
- 选自执行函数包裹的严格模式:
- 你在维护旧项目,需要和非严格模式的代码共存。
- 你需要隔离局部作用域,避免全局变量污染,同时在局部使用严格模式。
- 不过现在更推荐用ES6模块来做模块化和作用域隔离,这种自执行函数的写法更多是历史遗留的解决方案了。
作为第一门编程语言,JavaScript确实有不少容易混淆的细节,但你能主动测试和提问已经超棒了!慢慢来,多写多试,这些概念会越来越清晰的。
内容的提问来源于stack exchange,提问作者Starkemp315
相关产品推荐
相关产品推荐

