专栏首页小码农学习笔记一文看懂 JavaScript 闭包 - 闭包是什么
原创

一文看懂 JavaScript 闭包 - 闭包是什么

闭包

闭包的定义

红宝书(第3版):闭包是指有权访问另一个函数作用域中的变量的函数。(P178)

小黄书(上):当函数可以记住并访问所在的词法作用域时,就产生了闭包。(P44)

MDN:闭包可以让你从内部函数访问外部函数作用域。(原链接

大部分文章:当函数嵌套时,内层函数引用了外层函数作用域下的变量,并且内层函数在全局作用域下可访问时,就形成了闭包。

概括一下:

在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为(该外部函数的)闭包。

闭包的表现形式

  • 返回一个函数
  • 作为函数参数传递
  • 回调函数
  • 非典型闭包IIFE(立即执行函数表达式)

返回一个函数

这种形式的闭包在 JavaScript 中非常常见。

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

var bar = foo();
bar(); // 输出2,而不是1

作为函数参数传递

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

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

foo(); // 输出2,而不是1

回调函数

在定时器、事件监听、Ajax 请求、跨窗口通信、Web Workers 或者任何异步中,只要使用了回调函数,实际上就是在使用闭包

// 定时器
setTimeout(function timeHandler() {
  console.log('timer');
}, 100);

// 事件监听
$('#container').click(function() {
  console.log('DOM Listener');
});

IIFE(立即执行函数表达式)

IIFE(立即执行函数表达式)并不是一个典型的闭包,但它确实创建了一个闭包。

var a = 2;
(function IIFE() {
  console.log(a); // 输出2
})()

闭包的作用

  • 模块化(利用闭包的原理,将一个大的系统放在一个自调用函数中)
  • 防止变量被破坏(封装私有变量,保护函数内的变量安全)

如下代码所示,在开发一些组件的时候,要实现模块化就可以使用闭包:

var common = (function() {
  return {
    isStr:function() {
      ……
    },
    isNumber:function() {
      ……
    }
  }
})()

闭包内存释放

如果闭包使用不正确,会很容易造成内存泄漏,因此关注闭包是如何回收的能让你正确地使用闭包。

通常,如果引用闭包的函数是一个全局变量,那么闭包会一直存在直到页面关闭;但如果这个闭包以后不再使用的话,就会造成内存泄漏。

如果引用闭包的函数是个局部变量,等函数销毁后,在下次 JavaScript 引擎执行垃圾回收时,判断闭包这块内容如果已经不再被使用了,那么 JavaScript 引擎的垃圾回收器就会回收这块内存。

所以在使用闭包的时候,你要尽量注意一个原则:如果该闭包会一直使用,那么它可以作为全局变量而存在;但如果使用频率不高,而且占用内存又比较大的话,那就尽量让它成为一个局部变量。

当然了,如果想释放以全局变量形式存在的闭包,也可以用下面这种方式:

function foo() {
  var a = 5;
  return function() {
    a++;
    console.log(a);
  }
}
var bar = foo();

// 要想释放 bar 里面保存的 a,只能通过释放 bar
bar = null; // 或者 bar = undefined

文章持续更新,本文 GitHub 前端修炼小册 已经收录,欢迎 Star。如对文章内容有不同见解,欢迎留言交流。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JavaScript 的闭包是什么

    本文翻译自 w3schools: 原文地址:https://www.w3schools.com/js/js_function_closures.asp 译文地址...

    张拭心 shixinzhang
  • 什么是JavaScript 的闭包???

    Javascript的闭包是指一个函数与周围状态(词法环境)的引用捆绑在一起(封闭)的组合,在JavaScript中,每次创建函数时,都会同时创建闭包。闭包是一...

    AlbertYang
  • 深入理解JavaScript闭包之什么是闭包

    在看本篇文章之前,可以先看一下之前的文章 深入理解JavaScript 执行上下文 和 深入理解JavaScript作用域,理解执行上下文和作用域对理解闭包有很...

    木子星兮
  • 什么是闭包?为什么使用闭包?闭包的缺点?

       3. 调用外层函数,获得内层函数的对象,保存在外部的变量中——形成了闭包。  

    TimothyJia
  • 什么是闭包

    闭包 Closures,最初接触大概是在看 Swift 文档的时候,但是似是而非,好像明白了,好像就没彻底明白,记得当时也查了一些资料,终究是没彻底弄清楚。

    七适散人
  • JavaScript中的闭包到底是什么?

    即使是短暂接触JavaScript的初学者,想必也一定听说过“闭包”。本文将介绍有关闭包的全部内容,但文中并不会经常出现这个词。

    人工智能小咖
  • JavaScript 的闭包用于什么场景

    本文翻译自 MDN ( Mozilla Developer Network ): 原文地址:MDN 译文地址:shixinzhang 的博客 词法作用域 考虑如...

    张拭心 shixinzhang
  • 说说Python中闭包是什么?

    小猿会从最基础的面试题开始,每天一题。如果参考答案不够好,或者有错误的话,麻烦大家可以在留言区给出自己的意见和讨论,大家是要一起学习的 。

    程序IT圈
  • 说说Python中闭包是什么?

    答:可以将闭包理解为一种特殊的函数,这种函数由两个函数的嵌套组成,外函数和内函数。在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返...

    用户1564362
  • 面试题-python 什么是闭包(closure)?

    前面学了装饰器,那么闭包和装饰器有什么区别呢? 闭包传递的是变量,而装饰器传递的是函数对象,只是传的参数内容不一样,闭包的概念包含了装饰器,可以说装饰器是闭包的...

    上海-悠悠
  • 面试官问我:什么是JavaScript闭包,我该如何回答?

    闭包,有人说它是一种设计理念,有人说所有的函数都是闭包。到底什么是闭包?这个问题在面试的时候经常都会被问,很多小白一听就懵逼了,不知道如何回答好。

    用户8671053
  • 面试官,你为什么老是问我”闭包“

    写这边博文的背景是前段时间在参加深圳鹏城实验室后台研发工程师一职时被问及闭包是什么,之前对闭包的理解只是停留在使用层面,并未做深层次的了解。我的回答是闭包可以让...

    Dabelv
  • JavaScript进阶教程(5)-一文让你搞懂作用域链和闭包

    在JS中变量可以分为局部变量和全局变量,对于变量不熟悉的可以看一下我这篇文章:搞懂JavaScript全局变量与局部变量,看这篇文章就够了 作用域就是变量的使用...

    AlbertYang
  • 用最简单的语言解释Python的闭包是什么?

    Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西。

    马哥linux运维
  • 用最简单的语言解释Python的闭包是什么?

    Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西。

    刀刀老高
  • 公司新来的女实习生问我什么是闭包?

    看不懂没关系,等阅读完本文后,回头再来看这个故事,你会发现你已经完全了解了我的魅力,咳咳@¥%#…………JavaScript中闭包的魅力。

    童欧巴
  • 深入理解javascript原型和闭包(1)——一切都是对象

    “一切都是对象”这句话的重点在于如何去理解“对象”这个概念。 ——当然,也不是所有的都是对象,值类型就不是对象。 首先咱们还是先看看javascript中一个常...

    前朝楚水
  • 看完这篇文章还不懂Python中的闭包,请拍死小编

    小小科
  • 到底什么是CDN?一文看懂

    可是,大家在追剧的时候,有没有想过一个问题——为什么有时候明明自己手机的网速很快,但观看视频时,仍然卡顿?

    用户6543014

扫码关注云+社区

领取腾讯云代金券