和其它语言一样,函数或者说方法,都有自己的作用域。通过不同的代码块管理,来实现变量、函数、功能等隐藏,最终目标:高聚敛、低耦合
var a = 1;
function foo() {
var a = 2;
console.log(a); // 2
}
foo();
console.log(a); // 1
我们通过foo函数,将内部变量隐藏起来,看似很好,但是我们确污染了全局对象,因为foo方法被加入到全局对象中,而且我们还需要多写一行代码foo()来主动执行;
那有没有不污染全局对象,又能直接执行的方式呢?
当然有咯,而且这种方式还有个名称:IIFE(Immediately Invoked Function Expression)【立即执行函数表达式】
var a = 1;
(function foo(){
var a = 2;
console.log(a); // 2
})();
console.log(a); // 1
console.log(window.foo) // undefined
IIFE这种方式满足了我们所有的需求。这就是早期jQuery的实现方式!!!第一个()所包裹的是一个函数表达式,因此,我们在后面添加括号也就是 第二个()时,该函数表达式就立即执行了。
上面的IIFE函数名可以省略(function (){...})();但是,好的做法是给定一个函数名。另外,我们也可以给IIFE传递参数:
var a = 1;
(function foo(global){
var a = 2;
console.log(a, global.a); // 2 1
})(window);
console.log(a); // 1
另外,IIFE也可以避免一些问题:
var undefined = true; // 大坑!
(function foo(undefined){
var a;
if (a === undefined) {
console.log("undefined is safe here");
}
})();
还有一种写法,目前也是被广泛使用的,UMD(Universal Module Definition)
(function IIFE(def) {
def(window);
})(function def(global) {
var a = 3;
console.log(a, global.a); // 3 2
});
函数表达式def定义在片段的第二部分,然后当作参数(这个参数也叫作 def)被传递进 IIFE 函数定义的第一部分中。最后,参数 def(也就是传递进去的函数)被调用,并将window传入当作global参数的值。