闭包

作者: d68caad2b350 | 来源:发表于2020-06-15 16:24 被阅读0次

    1 闭包的含义

    1.1MDN上对闭包的解释

    函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在 JavaScript 中,每当函数被创建,就会在函数生成时生成闭包。

    1.2我对闭包的理解

    每个函数都是一个闭包,函数F()在其私有空间定义的变量在函数空间外是不可见的,由于F()是可以在全局空间中被调用的,所以在函数中新定义并返回一个新的Inner()函数,用来返回F()的的私有变量,从而生成一个可以访问F()私有空间的新的全局函数。

    下面是一个简单的闭包的例子:

    function F(param) {

        var N = function() {

            return param;

        }

        param++;

        return N;

    }

    >var inner = F(123)

    >inner();

    124

    inner()返回的是递增更新之后的值,由此可以看出,函数所绑定的是作用域本身,而不是一个值。

    2 常见的闭包错误

    2.1 错误代码

    function F() {

        var arr = [], i;

        for (i = 0; i < 3; i++) {

            arr[i] = function () {

                return i;

            };

        }

        return arr;

    }

    > var arr = F();

    >arr[0] () ;  >arr[1] () ; >arr[2] () ;

    3 3 3

    这并不是我们想要的结果,因为我们在这里创建了三个闭包,它们都指向了一个共同的局部变量i,但是闭包并不会记录它们的值,它们所拥有的只是相关域在创建时的一个连接(即引用)。

    2.2 正确代码:

    方法一:即时函数

    function F() {

        var arr = [], i;

        for( i = 0; i < 3; i++) {

            arr[i] = (function (x) {

                return function () {

                    return x;

                }

            }(i));

        }

        return arr;

    }

    在这里,不再创建一个返回i的函数了,而是将i 传递给了另一个即时函数,在该函数中,i被赋值给了局部变量x,这样一来,每次迭代中的x就会拥有各种不同的值了。

    方法二:普通内部函数

    function F() {

        function binder(x) {

            return function() {

                return x;

            };

        }

        var arr = [], i ;

        for (i = 0; i < 3; i++) {

            arr[i] = binder(i);

        }

        return arr;

    }

    该方法是在每次迭代过程中,在中间函数内将i的值本地化。

    3 闭包的应用

    3.1 getter与setter

    假设现在有一个变量,表示某个特定区间内的值,我们不想把它暴露给外部,所以将它保护在相关函数的内部,然后引入两个额外的函数——一个用于获取变量值,另一个用于给变量重新赋值。

    3.2 迭代器

    function setup(x) {

        var i = 0;

        return function() {

            return x[i++];

        };

    }

    > var next = setup(['a','b','c']);

    >next();

    3.3回调

    function changeSize(size){

        return function(){ document.body.style.fontSize = size + 'px'; };

    }

    var size12 = changeSize(12);

    var size14 = changeSize(20);

    document.getElementById('size-12').onclick = size12;

    document.getElementById('size-20').onclick = size14;

    作为一个回调(事件触发时调用的函数)绑定到事件。

    参考:JavaScript面向对象编程指南(第二版)

    相关文章

      网友评论

          本文标题:闭包

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