浓缩解读前端系列书籍一周一章前端书

一周一章前端书·第5周:《你不知道的JavaScript(上)》

2017-10-29  本文已影响9人  梁同学de自言自语

第5章:作用域闭包

到底什么是闭包

function foo(){
    var a = 2;
    function bar(){
        console.log(a); //2
    }
    return bar;
}

var baz = foo();

闭包暴露的方式不止一种

var foo(){
    var a = 2;
    //闭包函数
    function baz(){
        console.log(a);; //2
    }
    //执行外部函数,将闭包函数通过参数的方式传递进去
    bar(baz)
}

var bar(fn){
    fn();
}

闭包是最熟悉的陌生人

function wait(message){
    setTimeout(function timer(){
        console.log(message);
    },1000)
}

上述代码等价于:

//全局的setTimout函数准备就绪
var setTimout = function(invokeFn){}
function wait(message){
    //timer内部函数拥有对mesage的访问权
    var timer = function(){
        console.log(message);
    }
    //执行setTimeout()函数,并将timer以参数方式传递进去
    setTimout(timer);
}
//参数传递一个name字符串,选择器字符串
function setupBot(name,selector){
    //通过选择器字符串初始化成jQuery对象
    //绑定点击事件
    $(selector).click(function activator(){
        //打印外部函数的name
        console.log('Activating:' + name);
    })
}

setupBot('Closure Bot 1','#bot_1');
setupBot('Closure Bot 2','#bot_2');

闭包解决了什么问题

1. 用闭包造块级作用域

for(var i=1;i<=5;i++){
    setTimtou(function timer(){
        console.log(i);  
    },0)
}
for(var i=1;i<=5;i++){
    (function(index){
        setTimtou(function timer(){
            console.log(index);  
        },0)
    })(i);
}
for(let i=1;i<=5;i++){
    setTimtou(function timer(){
        console.log(i);  
    },0)
}

2. 用闭包造模块

function CoolModule(){
    var something = 'cool';
    var another = [1, 2, 3];
    
    function doSomething(){
        console.log(something);
    }
    
    function doAnother(){
        console.log(another.join(","));
    }
    
    //对外暴露内部函数
    return {
        doSomething : doSomething,
        doAnother : doAnother
    }
}
//通过一个IIFE函数来包装
var foo = (function CoolModule(){
    var something = 'cool';
    var another = [1, 2, 3];
    
    function doSomething(){
        console.log(something);
    }
    
    function doAnother(){
        console.log(another.join(","));
    }
    
    //对外暴露内部函数
    return {
        doSomething : doSomething,
        doAnother : doAnother
    }
})();

foo.doSomething();  //cool
foo.doAnother();    //1,2,3
var foo = (function CoolModule(id){
    var moduleId = id;

    function showId(){
        console.log(moduleId);
    }

    function uppcaseId(){
        moduleId = moduleId.toUpperCase();
    }

    return{
        showId : showId,
        uppcaseId : uppcaseId
    }
})('fooModule');

foo.showId();
foo.uppcaseId();
foo.showId();
/**
 * 定义牛批哄哄的超级模块管理器
 */
var SuperModules = (function(){
    //所有的模块集合,以name作为key
    var moduleMap = {};
    
    function define(name,deps,impl){
        //获取依赖
        for(var i=0;i<deps.length;i++){
            deps[i] = moduleMap[deps[i]]        
        }
        //执行引入的模块,并以deps作为参数
        moduleMap[name] = impl.apply(impl,deps);
    }
    
    function get(name){
        reutrn moduleMap[name];
    }
    
    //暴露公共API
    return{
        define : define,
        get : get
    }
})()

/**
 * 先定义一个bar模块
 * 没有依赖,impl是一个执行函数
 */
SuperModules.define('bar',[],function(){
    function hello(name){
        return 'let me introduce:' + name;
    }
    return {
        hello : hello
    }
})

/**
 * 再定义一个foo模块
 */
SuperModules.difine('foo',['bar'],function(bar){
    var hungry = 'hippo';
    
    function awesome(){
        console.log(bar.hello(hungry).toUpperCase());
    }
    
    return {
        awesome : awesome
    }
})

/**
 * 调用测试
 */
var bar = SuperModules.get('bar');
var foo = SuperModules.get('foo');

//let me introduce: hippo
console.log(bar.hello('hippo'));
//let me introduce: HIPPO
foo.awesome();
function hello(name){
    return 'let me introduce:' + name;
}
export hello;
import hello from 'bar';

var hungry = 'hippo';
function awesome(){
    console.log(bar.hello(hungry).toUpperCase());
}
export awesome;
module foo from 'foo';
module bar from 'bar';

//let me introduce: hippo
console.log(bar.hello('hippo'));
//let me introduce: HIPPO
foo.awesome();

小结

上一篇 下一篇

猜你喜欢

热点阅读