js闭包的理解

一、闭包的定义

百度百科对闭包的定义 

闭包就是能够读取其他函数内部变量的函数。

在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

 二、对闭包的理解

首先,我们阅读第一句话,也就是百度百科对闭包的定义:闭包就是能够读取其他函数内部变量的函数。那么,我们可以理解为闭包是一段特殊的代码片段,它具有以下几个特点:

1、存在两个函数(函数f1、函数f2)

2、函数f1内部存在一个内部变量n(注意n是f1的内部变量,即局部变量)

3、函数f2可以访问函数内部变量n

正常打码逻辑如下,但是我们发现函数f2并不能访问函数f1的内部变量n

function f1(){
  var n=999;
}
function f2(){
 alert(n); // error
}

那么,函数2如何访问函数1内部的变量n呢,继续往下读:在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数。

function f1(){
    var n=999;
    function f2(){
    alert(n); //999
  }
}

上面代码片段已经具备了闭包的3个特点,我们就可以说它就是一个闭包 。

那么,我们如何理解最后一句话:在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

这句话,是从本质上对闭包进行了个说明,即闭包的作用,闭包存在的意义,如下代码段

function f1(){
  n=1;
  function f2(){
        n++
    alert(n);
  }
  return f2;
}
var result=f1();
result(); // 2
result(); // 3

也有人说,这才是一个完整的闭包,因为它实现了在函数外部访问函数内部的变量。

这都是对闭包本质的一种解读,但是并不是十分的准确,我更倾向于他是闭包的使用方式,或者说是一个有实际使用意义的闭包。

还有一种说法也比较多:凡是访问函数内部的变量的都叫闭包,我对下面两种说法的解读是:

说法一:在函数外部访问函数内部的变量都是闭包

在函数外部访问函数内部的变量都是闭包,但是闭包并不一定都是从函数外部访问函数内部变量。从定义闭包就是能够读取其他函数内部变量的函数上来看,并没有规定一定要从函数外部访问函数内部的变量。能够读取其他函数(f1)内部变量(n)的函数(f2),即下面代码就是闭包。

function f1(){
    var n=999;
    function f2(){
    alert(n); //999
  }
}

说法二:凡是访问函数内部的变量的都叫闭包

闭包全部可以访问函数内部的变量,但是可以访问函数内部的变量的不一定是闭包。

如下,函数内部访问到了函数内部的变量,符合说法二,但很明显不符合闭包定义,不是闭包。

function f1(){
 var n=1;
 alert(n); // 1
}

总结:

根据定义闭包就是能够读取其他函数内部变量的函数,符合下面特点的代码段就是闭包

1、存在两个函数(函数f1、函数f2)

2、函数f1内部存在一个内部变量n(注意n是f1的内部变量,即局部变量)

3、函数f2可以访问函数内部变量n

//最简闭包
function f1(){
    var n=999;
    function f2(){
    alert(n); //999
  }
}

三、闭包的进一步解读

从上述文章中我们可以知道这是一个闭包,但是实际上它并没有任何意义

//最简闭包
function f1(){
    var n=999;
    function f2(){
    alert(n); //999
  }
}

为什么这么说呢,因为函数f2虽然可以访问到函数f1的内部变量n,但是实际代码执行的话定没有执行,最终会被js的垃圾回收机制判断为无用变量,从而进行回收。那么我们如何让上面代码变得可用呢?

function f1(){
    var n=1;
    function f2(){   
      n++
      alert(n); 
  }
    return f2;
}
var result =f1()
result(); // 2
result(); // 3

这便是一个有实际应用意义的闭包,所有有好多人认为这才是闭包。

在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是2,第二次的值是3。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制回收。

四、闭包强化(练习题)

1、代码:

let foo = function(){
    let i = 0;
    return function(){
        console.log(i++);
    }
}
let f1 = foo();
let f2 = foo();
f1();// 0
f2();// 0
f1();// 1

解释:

首先,第一个输出,因为前置运算,i要先参与输出,然后再自增,所以输出为0

第二个输出,因为f1和f2是不同的函数,不共享i变量,所以输出也为0

第三个输出,因为是f1,共享i,所以i加了1,输出为1

2、代码:

function fun(n,o) {
  console.log(o)
  return {
    fun:function(m){
      return fun(m,n);
    }
  };
}
var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,?,?,?
var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?
//问:三行a,b,c的输出分别是什么?

解释:

参考链接:JS闭包 经典面试题_js闭包面试题_xinyuan_java的博客-CSDN博客

//a: undefined,0,0,0
//b: undefined,0,1,2
//c: undefined,0,1,1

五、闭包的使用场景

理解js闭包10大使用场景,大厂面试官好自为之!_闭包的应用场景_编程界小明哥的博客-CSDN博客

后面不想写了,等有时间再更新吧

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值