1. 程式人生 > >《你不知道的JavaScript(上卷)》筆記:作用域閉包

《你不知道的JavaScript(上卷)》筆記:作用域閉包

  • 當函式可以記住並訪問所在的詞法作用域時,就產生了閉包,即使函式是在當前詞法作用域之外執行。
        function foo() {
            var a = 2;
            function bar(){
                console.log(a);
            }
            return bar;
        }
        var baz = foo();
        baz(); // 2
  • 無論通過何種手段將內部函式傳遞到所在的詞法作用域意以外,他都會持有對原始定義作用域的引用,無論在何處執行這個函式,都會使用閉包。
  • 無論何時何地,如果將函式當作第一級的值型別併到處傳遞,就會看到閉包在這些函式的應用。只要使用了回撥函式,實際上就是在使用閉包。
  • for迴圈中的閉包

    for (var i = 0; i < 5; i++) {
        (function (j) {
            setTimeout(function timer() {
                console.log(j);
            }, 1000 * j);
        })(i);
    }
    

模組

  • 基礎
function CoolModule() {
    var something = 'cool';
    var
another = [1,2,4]; function doSomething() { console.log( something ); } function doAnother() { console.log(another.join(' ! ')); } return { doSomething: doSomething, doAnother: doAnother } } var foo = CoolModule(); foo.doSomething(); foo.doAnother();
  • 單例模式
var foo = (function CoolModule() {
    var something = 'cool';
    var another = [1,2,4];

    function doSomething() {
        console.log( something );
    }

    function doAnother() {
      console.log(another.join(' ! '));
    }  

    return {
        doSomething: doSomething,
        doAnother: doAnother
    }
})();

foo.doSomething();
foo.doAnother();
  • 修改公共API
var foo = (function CoolModule(id) {
    function change() {
        publicAPI.identify = identify2;
    }

    function identify1() {
        console.log( id );
    }

    function identify2() {
      console.log(id.toUpperCase);
    }  

    var publicAPI = {
        change: change,
        identify: identify1
    }

    return publicAPI;
})('foo module');

foo.identify(); //foo module
foo.change();
foo.identify(); // FOO MODULE
  • 現代模組機制
var MyModules = (function Manager(){
    var modules = {};

    // name:模組明  deps:依賴模組  impl:模組實現的功能
    function define(name, deps, impl) {
        for(var i = 0; i < deps.length; i++){
            deps[i] = modules[deps[i]];
        }
        modules[name] = impl.apply(impl, deps);
    }

    function get(name) {
        return modules[name];
    }

})();

MyModules.define("bar", [], function(){
    function hello(who) {
        return "Let me introduce: " + who;
    }
    return {
        hello: hello
    }
})

MyModules.define("foo", ['bar'], function() {
    var hungry = "Hippo";
    function awesome() {
        console.log(bar.hello(hungry).toUpperCase());
    }

    return {
        awesome: awesome
    }
});

var bar = Mymodules.get("bar");
var foo = Mymodules.get("foo");
// let me introduce: hippo
console.log( bar.hello("hippo") );
// LET ME INTRODUCE: HIPPO
foo.awesome();
  • 未來模組機制:import、export、module

小結

  • 當函式可以記住並訪問所在的詞法作用域,即使函式上在當前詞法作用域之外執行,這時就產生了閉包。
  • 模組有2個主要特徵:(1)為建立內部作用域而呼叫了一個包裝函式;(2)包裝函式的返回值必須至少包含一個對內部函式的引用,這樣就會建立涵蓋整個包裝函式內部作用域的閉包。