考虑:
var module = {};
(function(exports){
exports.notGlobalFunction = function() {
console.log('I am not global');
};
}(module));
function notGlobalFunction() {
console.log('I am global');
}
notGlobalFunction(); // Outputs "I am global"
module.notGlobalFunction(); // Outputs "I am not global"
这里发生了什么?我知道如果你调用
notGlobalFunction()
,它只会调用第二个函数。
但是
var module = {}
在做什么呢?为什么在第一个函数中再次调用它?
上面说这是俗称的自执行匿名函数,那是什么意思呢?
立即调用的函数通常用于创建一个局部函数作用域,该作用域是私有的,不能被外界访问,并且可以定义自己的局部符号而不影响外界。这通常是一种很好的做法,但在这种特殊情况下,除了增加几行代码之外,我看不出它有任何好处,因为它没有用于任何用途。
这段代码:
(function(exports){
exports.notGlobalFunction = function() {
console.log('I am not global');
};
}(module));
如果没有这样的立即调用,将与一段代码相同:
module.notGlobalFunction = function() {
console.log('I am not global');
};
唯一不同的是,首先,创建了一个名为
modules
的 exports
的别名,它是立即调用的功能块的本地名称。但是,别名并没有做任何独特的事情,代码也可以直接使用modules
。
变量
modules
被创建为单个全局父对象,然后可以将许多其他全局变量作为属性保存。这通常称为“名称空间”。这通常是一个很好的设计模式,因为它最大限度地减少了可能与同一项目/页面中使用的其他代码片段发生冲突的顶级全局变量的数量。
所以不要像这样创建多个顶级变量:
var x, y, z;
可以像这样制作一个顶级变量:
var modules = {};
然后,将所有其他全局变量作为属性附加到它:
modules.x = 5;
modules.y = 10;
modules.z = 0;
这样,虽然仍然有多个全局变量,但只有一个顶层全局变量可能会与其他代码片段发生冲突。
类似地,立即调用的函数会创建一个局部的私有作用域,在该作用域中可以创建局部于该作用域并且不会干扰其他代码片段的变量:
(function() {
var x, y, z;
// variables x, y and z are available to any code inside this immediately invoked function
// and they act like global variables inside this function block and
// there values will persist for the lifetime of the program
// But, they are not truly global and will not interfere with any other global
// variables and cannot be accessed by code outside this block.
// They create both privacy and isolation, yet work just as well
})();
将参数传递给立即调用的函数只是一种将值传递给立即调用的函数范围的方法,该范围将具有自己的局部符号:
(function(exports) {
// Creates a local symbol in this function block called exports
// that is assigned an initial value of module
})(module);
这将创建一个新的空对象:
var module = {};
它的作用与:
var module = new Object();
这个包装纸:
(function(exports){
...
}(module));
只完成在函数内部为变量
module
添加别名。由于该匿名函数内部没有局部变量或函数,因此您可以在没有它的情况下执行相同的操作:
module.notGlobalFunction = function() {
console.log('I am not global');
};
像这样的匿名函数可以用来创建一个私有变量:
(function(exports){
var s = 'I am not global';
exports.notGlobalFunction = function() {
console.log(s);
};
}(module));
现在添加到
notGlobalFunction
对象的方法module
可以访问变量s
,但其他代码无法访问它。
IIFE 正在向作为参数传入的
module
对象添加一个方法。该代码演示了函数创建范围。具有相同名称的方法被添加到对象和浏览器的头部对象(窗口)。
“自动执行”可能会产生误导。它是一个匿名函数表达式,它不是被赋值或作为参数给定的,而是被调用的。在这里阅读立即调用的函数表达式(IIFE)。
var module = {} 在做什么?
它初始化一个充当命名空间的空对象。
为什么在第一个函数中又调用了它?
它不是“被调用的”,也不是第一个函数的“内部”。该对象作为参数(“导出”)提供给 IEFE,并且在内部有一个分配给它的属性。