美文网首页
js里闭包现象

js里闭包现象

作者: 认真敲代码的一条咸鱼 | 来源:发表于2020-01-07 20:52 被阅读0次

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

下面用一些代码来解释这个定义。

function foo() {

var a = 2;

function bar() {

console.log( a ); // 2

}

bar();

}

foo();

这段代码看起来和嵌套作用域中的示例代码很相似。基于词法作用域的查找规则,函数bar() 可以访问外部作用域中的变量 a(这个例子中的是一个 RHS 引用查询)。

这是闭包吗?

技术上来讲,也许是。但根据前面的定义,确切地说并不是。我认为最准确地用来解释bar() 对 a 的引用的方法是词法作用域的查找规则,而这些规则只是闭包的一部分。(但却是非常重要的一部分!)

从纯学术的角度说,在上面的代码片段中,函数 bar() 具有一个涵盖 foo() 作用域的闭包(事实上,涵盖了它能访问的所有作用域,比如全局作用域)。也可以认为 bar() 被封闭在了 foo() 的作用域中。为什么呢?原因简单明了,因为 bar() 嵌套在 foo() 内部。但是通过这种方式定义的闭包并不能直接进行观察,也无法明白在这个代码片段中闭包是如何工作的。我们可以很容易地理解词法作用域,而闭包则隐藏在代码之后的神秘阴影里,并不那么容易理解。

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

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(),实际上只是通过不同的标识符引用调用了内部的函数 bar()。bar() 显然可以被正常执行。

          但是在这个例子中,它在自己定义的词法作用域以外的地方执行。在 foo() 执行后,通常会期待 foo() 的整个内部作用域都被销毁,因为我们知道引擎有垃圾回收器用来释放不再使用的内存空间。由于看上去 foo() 的内容不会再被使用,所以很自然地会考虑对其进行回收。而闭包的“神奇”之处正是可以阻止这件事情的发生。事实上内部作用域依然存在,因此没有被回收。谁在使用这个内部作用域?原来是 bar() 本身在使用。拜 bar() 所声明的位置所赐,它拥有涵盖 foo() 内部作用域的闭包,使得该作用域能够一直存活,以供 bar() 在之后任何时间进行引用。bar() 依然持有对该作用域的引用,而这个引用就叫作闭包。因此,在几微秒之后变量 baz 被实际调用(调用内部函数 bar),不出意料它可以访问定义时的词法作用域,因此它也可以如预期般访问变量 a。这个函数在定义时的词法作用域以外的地方被调用。闭包使得函数可以继续访问定义时的词法作用域。当然,无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时都可以观察到闭包。

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; // 将 baz 分配给全局变量

}

function bar() {

fn(); // 妈妈快看呀,这就是闭包!

}

foo();

bar(); // 2

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

下雪了。下雪天果然跟被窝很配。

相关文章

  • js里闭包现象

    当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。 下面用一些代码来解释这...

  • php之闭包函数(Closure)

    php闭包函数(Closure) JS闭包 js和php闭包使用和区别

  • JS闭包入门

    最近有看到朋友的面经里提到的JS闭包的问题,就想研究研究,以下是我对JS闭包的简单理解。 到底什么是JS闭包? 定...

  • JS闭包

    JS闭包 闭包练习

  • JS闭包问题(二)

    在之前的JS闭包问题(一)文章中大概介绍了一下JS闭包,同时讲了闭包与变量之间的问题,今天我们继续聊闭包,聊聊闭包...

  • 闭包现象

    在一个函数内部,有权访问另一个函数中的变量(并且能够随时访问)! 尽量不要去看长篇大论关于闭包的解释,很容易把自己...

  • 闭包现象

    一、什么是闭包?声明一个变量,声明一个函数,在函数内部访问外部的变量,那么这个函数加这个变量叫做闭包。 二、闭包有...

  • JS闭包大结局(JS闭包系列3)

    在上一篇中再谈JS闭包(JS闭包系列2),我详细的介绍了JS中的变量作用域相关的概念,结合第一节关于JS闭包(JS...

  • JS里的闭包

    一、封闭函数 封闭函数的定义:将函数封装起来一般写法:(function(){-----})()最后的括号表示马上...

  • 学习JavaScript闭包和作用域笔记

    JS JavaScript闭包和作用域 闭包 JavaScript高级程序设计中对闭包的定义:闭包是指有权访问另外...

网友评论

      本文标题:js里闭包现象

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