什么是闭包?

冷不防 2022-11-26 14:56 250阅读 0赞

我们都知道一个概念。

在JS当中,一个函数可以访问其外部的变量资源。

format_png

一个典型的代码

但以下这种情况会出错。

  1. function m1(){
  2. var a = 100;
  3. console.log(a++);
  4. }
  5. function m2(){
  6. console.log(a++); //这里无法访问a
  7. }

如果,我们想在m2的作用域里,访问m1里的变量,就像下面这样:

format_png 1

首先,我们可以在m1的内部创建一个函数m3

  1. function m1(){
  2. var a = 100;
  3. function m3(){
  4. console.log(a++);
  5. }
  6. }

format_png 2

m3可以正常访问a,接下来我们增加一个return操作。

  1. function m1(){
  2. var a = 100;
  3. return function m3(){
  4. console.log(a++);
  5. }
  6. }

既然有了返回值,那我们不妨接收一下,继续编写代码如下:

  1. function m1(){
  2. var a = 100;
  3. return function m3(){
  4. console.log(a++);
  5. }
  6. }
  7. var _m3 = m1();

我们执行了函数m1, 并将返回值赋值给_m3

那么目前_m3m3函数是等价的,即它们是同一个函数。

有了_m3,一切都好办了。我们继续编写代码

  1. function m1(){
  2. var a = 100;
  3. return function m3(){
  4. console.log(a++);
  5. }
  6. }
  7. var _m3 = m1();
  8. function m2(){
  9. _m3();
  10. }

因为_m3是全局变量,因此m2可以调用_m3

也就等价于m2间接的,访问到了变量a

format_png 3

通常,我们管m3,叫做一个『 闭包函数 』

下面列举几个常见的闭包场景:

01

  1. for(var i=0; i<list.length; i++){
  2. var item = list[i];
  3. item.onclick = (function(num){
  4. return function(){
  5. //......
  6. }
  7. })(i);
  8. }

02

  1. function (){
  2. var that = this;
  3. setTimeout(function(){
  4. //......
  5. },2000)
  6. }

03

  1. function User(){
  2. var _age = 0;
  3. this.getAge = function(){
  4. return _age;
  5. }
  6. this.setAge = function(age){
  7. this._age = age;
  8. }
  9. }

04

  1. (function(){
  2. var cache = [...];
  3. return {
  4. get : function(){
  5. //...
  6. }
  7. };
  8. })()

05

  1. (function(){
  2. var t = null;
  3. return function(){
  4. if(!t){
  5. t = create();
  6. }
  7. }
  8. })()

为了创造闭包,有时候会写函数自调用

可以不这么麻烦么??

当然,那就是使用let。

例如

  1. for(let i=0; i<list.length; i++){
  2. let item = list[i];
  3. item.onclick = function(){
  4. console.log(i);
  5. //观察变量i的值
  6. };
  7. }

关于闭包的疑问

当函数m1执行完成的时候,内部的变量a,理论上应该被回收掉了。

format_png 4

可是为什么变量a依然可以被访问呢?

主要是因为,m3还在引用它

format_png 5

垃圾回收器显然不会回收一个依然被引用的变量。

除非这个变量,已经无人引用,即是说,它已经无法再内存里被找到。

此时才可以当做垃圾处理。

不过m3可以访问变量a这种规则,并不是在所有编程语言里都生效的。因此,这也算是JS的特性之一。

发表评论

表情:
评论列表 (有 0 条评论,250人围观)

还没有评论,来说两句吧...

相关阅读

    相关 什么

    我们都知道一个概念。 在JS当中,一个函数可以访问其外部的变量资源。 ![format_png][] 一个典型的代码   但以下这种情况会出错。 fun

    相关 什么

    闭包 我们都知道,js的作用域分两种,全局和局部,基于我们所熟悉的作用域链相关知识,我们知道在js作用域环境中访问变量的权利是由内向外的,内部作用域可以获得当前作用域下的

    相关 什么

            \----本文摘自programming in  lua 如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包

    相关 什么

    什么是闭包? 简单来说,闭包是指外部可以访问另一个函数作用域内的变量的函数,一般是定义在外层函数中的内层函数。 为什么需要闭包? 局部变量无法共享和长久的保存,而全局变量

    相关 什么

    闭包是指有权访问另一个函数作用域中变量的函数 作用:访问另一个函数作用域中变量 原理:通过匿名式函数把局部变量驻留在内存里,可以减少全局变量的使用 优点是封装性,

    相关 什么

    什么是闭包? 说明 闭包   有些读者可能很好奇,为什么闭包会成为一个独立的概念,以及为什么它需要编程语言提供额外的支持。这些疑惑可以本文中找到答案。

    相关 什么

    1.什么是闭包? 古老定义   闭包(closure),是指函数变量可以保存在函数作用域内,因此看起来是函数将变量“包裹”了起来   那这样说来,包含变量的函数就是闭

    相关 什么

    闭包 定义:闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链