《你不知道的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)包装函数的返回值必须至少包含一个对内部函数的引用,这样就会创建涵盖整个包装函数内部作用域的闭包。

猜你喜欢

转载自blog.csdn.net/wuweitiandian/article/details/79435544