闭包

作者: Amy_yqh | 来源:发表于2018-05-28 10:06 被阅读0次

    一、《JavaScript高级程序设计》这样描述:

    闭包是指有权访问另一个函数作用域中的变量的函数;

    《JavaScript权威指南》这样描述:

    从技术的角度讲,所有的JavaScript函数都是闭包:它们都是对象,它们都关联到作用域链。

    《你不知道的JavaScript》这样描述:

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

    二、闭包的经典栗子
    另一个很经典的例子就是for循环中使用定时器延迟打印的问题:

    for (var i = 1; i <= 10; i++) {
        setTimeout(function () {
            console.log(i);
        }, 1000);
    }
    

    在这段代码中,我们对其的预期是输出1~10,但却输出10次11。这是因为setTimeout中的匿名函数执行的时候,for循环都已经结束了,for循环结束的条件是i大于10,所以当然是输出10次11咯。
    究其原因:i是声明在全局作用中的,定时器中的匿名函数也是执行在全局作用域中,那当然是每次都输出11了。

    原因知道了,解决起来就简单了,我们可以让i在每次迭代的时候,都产生一个私有的作用域,在这个私有的作用域中保存当前i的值。

    for (var i = 1; i <= 10; i++) {
        (function () {
            var j = i;
            setTimeout(function () {
                console.log(j);
            }, 1000);
        })();
    }
    

    这样就达到我们的预期了呀,让我们用一种比较优雅的写法改造一些,将每次迭代的i作为实参传递给自执行函数,自执行函数中用变量去接收:

    for (var i = 1; i <= 10; i++) {
        (function (j) {
            setTimeout(function () {
                console.log(j);
            }, 1000);
        })(i);
    }
    

    三、闭包的应用
    闭包的应用比较典型是定义模块,我们将操作函数暴露给外部,而细节隐藏在模块内部:

    function module() {
        var arr = [];
        function add(val) {
            if (typeof val == 'number') {
                arr.push(val);
            }
        }
        function get(index) {
            if (index < arr.length) {
                return arr[index]
            } else {
                return null;
            }
        }
        return {
            add: add,
            get: get
        }
    }
    var mod1 = module();
    mod1.add(1);
    mod1.add(2);
    mod1.add('xxx');
    console.log(mod1.get(2));
    

    相关文章

      网友评论

          本文标题:闭包

          本文链接:https://www.haomeiwen.com/subject/nbuwjftx.html