• 也谈JavaScript闭包


    闭包对于很多JavaScript初学者来说,都是比较难以理解的一个概念。其实,闭包并不是那么难以掌握的,理解闭包,只需要学会3个的基本事实


    首先我们来看第一个事实,JavaScript允许当前函数引用外部定义的变量,如下:
    function makeSandwich() {
        var magicIngredient = "peanut butter";
        function make(filling) {
            return magicIngredient + " and " + filling;
        }
        return make("jelly");
    }
    makeSandwich(); // "peanut butter and jelly"
    上述代码中,函数make是可以使用magicIngredient这个变量的。这是因为,JavaScript首先会在make函数内部以及他的原型上寻找magicIngredient这个变量,结果没有找到,于是,他就会沿着词法环境(或者说是作用域链)向它上一级作用域寻找,于是,就在makeSandwich里找打了。
     
    接下来,我们再来看一下第二个事实,即使外部函数已经返回,当前函数依然可以使用外部函数的变量:
    function sandwichMaker() {
        var magicIngredient = "peanut butter";
        function make(filling) {
            return magicIngredient + " and " + filling;
        }
        return make;
    }
    var f = sandwichMaker();
    f("jelly"); // "peanut butter and jelly"
    f("bananas"); // "peanut butter and bananas"
    f("marshmallows"); // "peanut butter and marshmallows"
    这个例子与第一个例子几乎是一样的,只是,make函数不是直接在sandwichMaker里面直接执行,而是将他返回到函数外部,然后才执行。即使函数已经返回到外部了,f函数(也即make函数,其实他们的引用是一样的)依然记住magicIngredient变量的值。
     
    这是如何工作的呢?答案是,JavaScript的函数值包含的信息比它执行时所需要的信息还要多。而且,JavaScript函数内部存储了可能会用到的在外部定义的变量的引用(注意是引用,而不是值)。那些在其所涵盖的作用域内跟踪变量的函数称为闭包。这里的make函数就是闭包了,它引用了两个外部变量,magicIngredient和filling。每当make函数被调用时,都能够用到这两个变量,因为,他的内部已经存储了他们的引用( 指针)。
     
    函数可以引用其作用域内的任何变量,包括参数和和外部函数变量,上面的代码可以改成如下形式,使它更为灵活通用:
    function sandwichMaker(magicIngredient) {
        function make(filling) {
            return magicIngredient + " and " + filling;
        }
        return make;
    }
    var hamAnd = sandwichMaker("ham");
    hamAnd("cheese"); // "ham and cheese"
    hamAnd("mustard"); // "ham and mustard"
    var turkeyAnd = sandwichMaker("turkey");
    turkeyAnd("Swiss"); // "turkey and Swiss"
    turkeyAnd("Provolone"); // "turkey and Provolone"
    JavaScript还提供了一种通过字面量来创建闭包的方法,那就是函数表达式,如下:
    function sandwichMaker(magicIngredient) {
        return function(filling) {
            return magicIngredient + " and " + filling;
        };
    }
    我们会发现,这个函数表达式是一个匿名函数,但是,这并无影响的,因为,我们并没有在里面调用执行它。
     
    最后,我们来看一下第三个事实,闭包可以更新外面变量的值。
     
    事实上,闭包内部存储的是外部变量的引用地址,而不是外部变量的值的副本。光说是很难理解的,下面我们来看一个例子:
    function box() {
        var val = undefined;
        return {
            set: function(newVal) { val = newVal; },
            get: function() { return val; },
            type: function() { return typeof val; }
        };
    }
    var b = box();
    b.type(); // "undefined"
    b.set(98.6);
    b.get(); // 98.6
    b.type(); // "number"
    这个例子,box函数可以返回一个对象,这个对象具有3个闭包,分别是set,get,type,他们都可以访问到val这个变量,其中,set是设置val的值,get是获取val的值,type是获取val的值的类型。
     
    总结:
    1.函数可以引用定义在其外部的变量
    2.闭包比创建他们的函数具有更长的生命周期
    3.闭包内部存储了外部变量的指针,既可以读取他们,也可以修改。
  • 相关阅读:
    Linux网卡上添加多个IP
    TCP_Wrappers基础知识介绍
    工作、生活、思考、人生、经验、总结
    网络层安全
    centos7.0 安装nginx
    linux 下配置jdk
    yii2.0 中的队列
    centos7.0 activemq的安装
    solrCloud
    线性顺序表
  • 原文地址:https://www.cnblogs.com/yugege/p/4975160.html
Copyright © 2020-2023  润新知