我会尽力解释这一点,但我对它的理解来自凯尔·辛普森。他太棒了,你应该去看看他。 :-D
您正在询问有关立即调用函数表达式(IIFE)、向它们传递参数以及为什么有人会这样做的问题。
首先,在这种情况下使用 IIFE 的原因是为了限制变量的范围。
这很重要,因为随着程序变得越来越大并且添加了许多部分,您很容易会从一个变量到另一个变量发生冲突。
app.js 可以有
variable = "thing";
之后不久,somethingelse.js 就可以了
variable = "not thing";
这是一个大问题。在 JavaScript 中可以通过创建立即运行并运行一次的“模块”或函数来避免这种情况。
这样,您在函数中创建的变量和方法就不会“污染全局范围/命名空间”。
但是,如果您需要或想要全局窗口对象上可用的东西怎么办?
好吧,你可以通过将其添加到“窗口”(JavaScript 中的全局范围)来做到这一点。
(function Module(window){
var _thing = "private thing that only exists in this function";
window.thing = _thing;
//IS NOW AVAILABLE GLOBALLY AND EXPLICITLY ON WINDOW OBJECT
//window.onload you can wait for DOM/page before running the rest
})(window);
您还可以在函数中将其命名为您想要的任何名称:
(function niftyModule(global){
global.variable = "nifty text!";
})(window)
当您使用多个库时,这一点变得尤其重要。
出于某种原因,每个人都喜欢使用“$”作为他们的库的表示,这样你就可以访问他们的私有方法(它们实际上也只是 IIFE 中的函数!(这是构建好东西的一种非常流行的方式)。
那么,如果您使用 jQuery 和其他 2 个也使用 $ 访问其公共方法/api 的库该怎么办?
很简单,您可以通过将其作为参数传递来分配您想要在函数/模块范围内分配哪个变量!
(function NiftyModule(window, $){
//Now, every time you use $ in here it means jQuery and not something else!
})(window, jQuery);
尝试使用功能和范围非常重要。以不同的方式构建一些变量。
例如,是....
var text = "nifty text";
与
text = "nifty text";
如果你在函数内部做同样的事情怎么样?这两个版本有何不同?
另外,要习惯在 IIFE 中构建您自己的程序并适当限制您正在编写的代码的范围。
您还可以从具有您想要全局访问的方法和变量的函数返回对象,而无需将它们添加到 window 对象。
一开始很复杂,但将来它会为您省去很多麻烦和错误!
最后,在你的例子中:
//initialize a global variable called namespace. If this already
//existed then assign it the previous values. If not, make it an empty
//object.
var namespace = namespace || {};
//pass namespace into an IIFE. Within the IIFE refer to namespace as "o"
(function( o ){
//assign a variable to namespace
o.foo = "foo";
//assign a method to namespace
o.bar = function(){
return "bar";
};
})(namespace);
//now when you log namespace it will have those properties.
console.log(namespace);