JS系列(五):函数作用域

和其它语言一样,函数或者说方法,都有自己的作用域。通过不同的代码块管理,来实现变量、函数、功能等隐藏,最终目标:高聚敛、低耦合

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参数的值。

你可能感兴趣的:(JS系列(五):函数作用域)