IIFE 为您提供的唯一东西是一个封闭的范围。你不需要
多个 IIFE,除非您没有说明某些原因。所以,首先,
让我们介绍一下您阅读的“最佳实践”链接的真正含义。
在浏览器环境中,所有 JavaScript 都在一个范围内执行。
因此,以下两个脚本将具有相同的范围,尽管
不同的文件:
script_a.js
var foo = 'bar'
console.log('foo = ', foo)
script_b.js
if (foo === 'bar') {
console.log('foo is still bar')
}
但是如果我们将每个脚本包装在一个 IIFE 中,则范围会发生变化,script_b 将
不再起作用:
script_a.js
(function () {
var foo = 'bar'
console.log('foo = ', foo)
}())
script_b.js
(function () {
if (foo === 'bar') { // throws an error because `foo` is not defined
console.log('foo is still bar')
}
}())
鉴于 Web 开发的性质,以及带有插件的 jQuery,许多脚本可以
加载并且全局范围被污染。这可能导致难以识别
副作用。因此,建议您将代码包含在其
自己的范围。这是通过 IIFE 完成的,因为函数有自己的
本地作用域,函数在加载时调用。
根据您的example,您似乎只想要可组合的
对象,以便您可以在期间将它们分隔在单独的文件中
发展。这是module pattern的明确用法:
script_c.js
var MY_NAMESPACE = (function () {
var privateFoo = 'foo'
return {
getFoo: function getFoo () {
return privateFoo
}
}
}())
script_d.js
(function (NAMESPACE) {
var privateBar = 'bar'
NAMESPACE.getBar = function getBar () { return privateBar }
}(MY_NAMESPACE))
script_e.js
console.log(MY_NAMESPACE.getFoo()) // 'foo'
console.log(MY_NAMESPACE.getBar()) // 'bar'
注意MY_NAMESPACE 是一个全局变量。这是你必须要做的
是唯一的,因为它很容易被一些后来加载的内容覆盖
可能会覆盖您的全局变量的脚本。
我没用过,但是有一个叫stampit的库
扩展了这种模式并使其易于使用。
综上所述,您可以将 MY_NAMESPACE 对象扩展为
一个新对象:
script_f.js
var CHILD_NAMESPACE = Object.create(MY_NAMESPACE)
CHILD_NAMESPACE.fooOrBar = (function (NS) {
var counter = 0
return function () {
var answer = (counter % 2 === 0) ? NS.getFoo() : NS.getBar()
counter += 1
return answer
}
}(CHILD_NAMESPACE))
当然,以上所有脚本都可以包含在一个整体中
IFFE 将您的代码完全包含在自己的范围内。