New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

作用域闭包 #30

Open
paddingme opened this Issue Aug 22, 2015 · 0 comments

Comments

Projects
None yet
1 participant
@paddingme
Owner

paddingme commented Aug 22, 2015

  1. 看起来像闭包。

    function foo(){
        var a = 2;
        function bar(){
            console.log(a);
        }
        bar();
    }
    foo();
  2. 这才是闭包。

    function foo(){
        var a = 2;
        function bar(){
            console.log(a);
        }
        return bar;
    }
    var baz = foo();
    baz();
  3. 把内部函数 baz 传递给 bar, 当调用这个内部函数时(现在叫做 fn),它涵盖的 foo()
    内部作用域的闭包就可以观察到了。因此它能够访问 a。

    function foo() {
        var a = 2;
        function baz(){
            console.log(a);
        }
        bar(baz);
    }
    function bar(fn) {
        fn();
    }
  4. 把 baz 分配给全局变量

    var fn;
    function foo(){
        var a = 2;
        function baz(){
            console.log(a);
        }
        fn = baz;
    }
    function bar(){
        fn();
    }
    foo();
    bar();
  5. 无论通过何种手段将内部函数传递到所在的词法作用域以外,
    它都会持有对原始定义作用有的引用,
    无论在何处执行这个函数都会使用闭包。

    function wait(message) {
        setTimeout(function timer(){
            console.log(message);
        },1000)
    }
    wait("Hello,Closure!")

    /*
    jquery
    */

    function setupBot(name,selector){
        $(selector).click(function activator(){
            console.log("Activating: " + name);
        });
    }
    setupBot("console BOT1","#bot_1");
    setupBot("console BOT2","#bot_2");
  6. IIFE

    var a = 2;
    (function IIFE(){
        console.log(a);
    })();
  7. 循环和闭包

    for(var i = 1; i <= 5; i++) {
        setTimeout(function timer(){
            console.log(i)
        },i*1000)
    }
    
    
    for(var i = 0; i<=5; i++) {
        (function(j){
            setInterval(function(){
                console.log(j);
            },1000);
        })(i);
    }
    // 每隔一秒钟打印1,2,3,4,5
    function foo(arr){
        var i = 0;
        return function(){
            setInterval(function(){
                console.log(arr[i++]);
            },1000);
        }()
    }
    (function(arr){
        var i=0,length=arr.length;
        (function a(){
            setTimeout(function(){
                console.log(arr[i++]);
                i<length&&a();
            },1000)
        }())
    }([1,2,3,4]))
  8. 模块

function coolModule() {
     var sth = "cool";
     var another = [1,2,3];
     function doSth() {
        console.log(sth);
     }
     function doAnother() {
        console.log(another.join("!"));
     }
     return {
        doSth:  doSth,
        doAnother : doAnother
     }
}
var foo = new coolModule();
foo.doSth();
foo.doAnother();
  1. 模块模式需要两个必要条件:
    1. 必须有外部的封闭函数,该函数必须至少
      被调用一次(每次调用都会创建一个新的模块实例)
    2. 封闭函数必须至少返回至少一个内部函数,
      这样内部函数才能在私有作用域中形成闭包,
      并且可以访问或者修改私有的状态。
  2. 模块模式另一个简单强大的变化用法是,命名将要作为公共API 返回的对象。
``` js
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.change();
foo.identify();
```
  1. 现代的模块管理
``` js
var MyModules = (function Manger() {
    var modules = {};
    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];
    }
    return {
        define: define,
        get: get
    }
})();

MyModules.define("bar", [], function() {
    function hello(who) {
        return "Let me introduce: " + who;
    }
    return {
        hello: hello
    };
});
MyModules.define("foo", ["bar"], function(bar) {
    var hungry = "hippo";
    function awesome() {
        console.log(bar.hello(hungry).toUpperCase());
    }
    return {
        awesome: awesome
    };
});
var bar = MyModules.get("bar");
var foo = MyModules.get("foo");
console.log(bar.hello("hippo"));
foo.awesome();
```

当函数可以记住并访问所在的词法作用域,即使函数时在当前词法作用域之外执行,这时就产生了闭包。

模块有两个主要特征:

  1. 为创建内部作用域而调用了一个包装函数;
  2. 包装函数的返回值必须至少包含一个队内部函数的引用,这样就会创建涵盖整个包装函数内部作用域的闭包。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment