闭包

   闭包就是可以让函数访问该函数声明时的作用域内的所有变量和函数。

例如:

var outerName = 'closure';
function outerFunction(){
     console.log(outerName);   
}
outerFunction();   //closure

   接下来是关于()的有意思的用法。“()”紧跟在函数后面,表示立即调用该函数

例如:

var counter = (function() {
    var count = 0;
    return function () {
        return count++ ;
    }
}());

代码定义了一个立即执行函数并返回给counter,这个函数定义了一个局部变量count,返回了一个子函数,该子函数每次调用,都会把count加一并返回,下一次调用时会在上一次调用的基础上加一,可以想象成闭包将保护着count每一次运行的值。

等效于

var counter = (function() {
    var count = 0;
    return function () {
        return count++ ;
    }
});
counter();

 

需要避免的问题:

var add_the_handlers = function (nodes) {
    var i;
        for (i = 0; i < nodes.length; i++) {
            nodes[i].onclick = function (e) {
                console.log(i);
            };
        }
};

add_the_handlers函数本意是想传递给每个事件处理器一个唯一的值(i)。也就是每次点击nodes时,输出对应的 i 。但事实上,每次点击nodes,只会在控制台输出相同的值。

这是因为事件处理器函数绑定了变量 i 本身,而不是函数在构造时的变量 i 的值。换句话说闭包中输出的 i 是它所在作用域中的 i 的值,在循环结束后 i 的值变为4。而闭包本身绑定了变量 i ,输出的值会跟随变量 i 的变化而变化,最后输出4。

要使每次点击nodes时,输出对应的 i,可使用下述代码:

var add_the_handlers = function (nodes) {
    var i;
        for (i = 0; i < nodes.length; i++) {
            nodes[i].onclick = function (i) {
                return function(){
                    console.log(i);
                };
            }(i);
        }
};

这里使用一个立即执行函数并传递当前的 i 值即上面的(i),返回一个新的函数。在这个新生成的函数的闭包中保存了当前的 i 值。这样可以得到想要的结果了。

还有一个和变量提升有关的容易混淆的东西:

var name = 'webLearner';
function f(){
     console.log('1:' + name);
     var name = 'Lucky';
     console.log('2:' + name);   
}
f();
#result
//undefined
//Lucky

 

如转载请注明出处!

posted @ 2016-07-27 17:12  Ninja_MM  阅读(114)  评论(0编辑  收藏  举报