资讯专栏INFORMATION COLUMN

闭包

weizx / 2352人阅读

摘要:而闭包的神奇之处在于可以阻止这件事情的发生。依然持有对该作用域的引用,而这个引用就叫做闭包。当然,无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时都可以观察到闭包。

下面我们来看一段代码,清晰地展示了闭包:

function foo(){
    var a=2;
    function bar(){
        console.log(a);
    }
    return bar;
}
var baz=foo();
baz()     //2,这就是闭包

函数bar()的词法作用域能够访问foo()的内部作用域,然后我们将bar()函数本身当作一个值类型进行传递。在这个例子中,我们将bar
所引用的函数对象本身当作返回值。
foo()执行后,其返回值(也就是内部的bar()函数)赋值给变量baz并调用baz(),实际上只是通过不同的标识符引用调用了内部的函数
baz().虽然baz()被正常执行,但是它是在自己定义的词法作用域以外的地方执行。
由于存在引擎垃圾回收器来释放不再使用的内存空间,由于看上去foo()的内容不会再被引用,所以很自然地会考虑对其进行回收。
而闭包的神奇之处在于可以阻止这件事情的发生。所以内部作用域依然存在,而且就是baz()本身在使用。
bar()依然持有对该作用域(foo())的引用,而这个引用就叫做闭包。
当然,无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时都可以观察到闭包。

function foo(){
    var a=2;
    function baz(){
        console.log(a);//2
    }
    bar(baz);
}
function bar(fn){
    fn();   //这就是闭包
}

把内部函数baz传递给bar,当调用这个内部函数是(现在叫做fn),它涵盖的foo()内部作用域的闭包就可以观察到了,因为他能够访问a。

传递的函数当然也可以是间接的:

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

所以无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包。

上面是为了可以解释如何使用闭包而故意在结构上加了些许修饰,下面我们来看日常使用到的闭包。

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

将一个内部函数(timer)传递给setTimeout(...).timer具有涵盖wait()作用域的闭包,因此还保有对变量message的引用。
在引擎内部,内置的工具函数setTimeout()持有对一个参数的引用,这个参数也许叫做fn或者fnc,或者其他类似的名字。引擎会调用这个函数,
在例子中就是内部的timer函数,而词法作用域在这个过程保持完整。

再来看一个jq的:

function setupBot(name,selector){
    $(selector).click(function activator(){
        console.log("Activating:"+name);
    });
}
setupBot("Closure Bot1","#bot_1");
setupBot("Closure Bot2","#bot_2");

本质上无论何时何地,如果将(访问他们各自词法作用域的)函数当作第一级的值类型并导出传递,你就会看到闭包在这些函数中的应用。在定时器、
事件监听器、Ajax请求、跨窗口通信,Web Workers或者任何其他异步(或者同步)任务中,只要使用了回调函数,实际上就是在使用闭包!
(参考《你不知道的JavaSctipt上卷》)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94924.html

相关文章

  • JS 中的闭包是什么?

    摘要:大名鼎鼎的闭包面试必问。闭包的作用是什么。看到闭包在哪了吗闭包到底是什么五年前,我也被这个问题困扰,于是去搜了并总结下来。关于闭包的谣言闭包会造成内存泄露错。闭包里面的变量明明就是我们需要的变量,凭什么说是内存泄露这个谣言是如何来的因为。 本文为饥人谷讲师方方原创文章,首发于 前端学习指南。 大名鼎鼎的闭包!面试必问。请用自己的话简述 什么是「闭包」。 「闭包」的作用是什么。 首先...

    Enlightenment 评论0 收藏0
  • 闭包,又见闭包。。。。?

    摘要:完美的闭包,对,闭包就这么简单。这仅仅是闭包的一部分,闭包利用函数作用域达到了访问外层变量的目的。此时一个完整的闭包实现了,的垃圾回收机制由于闭包的存在无法销毁变量。 1.闭包是指有权访问另一个函数作用域中的变量的函数。 上面这段话来自 javascript 高级程序设计 第三版 P178 。作者说闭包是一个函数,它有访问另一个函数作用域中的变量的能力。 2.函数访问它被创建时所处的...

    keelii 评论0 收藏0
  • 多层级理解闭包

    摘要:第二梯队理解有了第一梯队的认识,我们慢慢修正大脑中对闭包的认识。理解这句话就可以很好的与闭包这两个字关联起来理解闭包这个概念了。总结第二梯队理解闭包是一个有特定功能的函数。第四梯队理解闭包通过访问外部变量,一个闭包可以维持这些变量。 闭包 闭包的概念困惑了我很久,记得当时我面试的时候最后一面有一个问题就是问题关于闭包的问题,然而到现在已经完全不记得当时的题目是啥了,但仍然能够回忆起当时...

    nemo 评论0 收藏0
  • 面试官问我:什么是JavaScript闭包,我该如何回答

    摘要:到底什么是闭包这个问题在面试是时候经常都会被问,很多小白一听就懵逼了,不知道如何回答好。上面这么说闭包是一种特殊的对象。闭包的注意事项通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。从而使用闭包模块化代码,减少全局变量的污染。 闭包,有人说它是一种设计理念,有人说所有的函数都是闭包。到底什么是闭包?这个问题在面试是时候经常都会被问,很多小白一听就懵逼了,不知道如何回答好。这个...

    BenCHou 评论0 收藏0

发表评论

0条评论

weizx

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<