所有栏目 | 云社区 美国云服务器[国内云主机商]
你的位置:首页 > 云社区 » 正文

如何才能通俗易懂的解释javascript里面的‘闭包’?

发布时间:2020-04-12 08:37:03

资讯分类:闭包  javascript  通俗易懂  解释  函数  组合  抽象
如何才能通俗易懂的解释javascript里面的‘闭包’?

网上对闭包的解释都太专业了!我给个「非专业」的解释!有不对的地方,还望指正!


编程的本质是什么?是抽象+组合

  • 面向过程编程将业务抽象为数据结构+方法(过程),通过方法的组合来解决问题

  • 面向对象编程将业务抽象为一个个的对象,通过对象间的组合通信来解决问题

  • 函数式编程将业务抽象为一个个的函数,通过函数间的组合来解决问题

但是每种抽象方式都不是万能的。都是擅长某些方面,而不太擅长某些方面(否则就不会有越来越多的语言支持多种编程范式了。)而大部分的语言特性就是用来弥补自身不擅长的地方。比如闭包。


「闭包」的作用就是为了「实例化」函数「实例化」的目的是为了保持状态

我们来看一个OO的例子,我有一个类:

class Calc{
private int num;
public Calc(int num){

this.num

= num;
}
public int calc(int x) {
return x + num;
}
}

通过这个类,我就能实例化出来多个不同状态的对象:

addOne = new Calc(1);
addTwo = new Cacl(2);
addOne.calc(1); // 2
addTwo.calc(2); // 3

你可能会说,这在js里还不简单,定义个函数就可以了啊。

function add(a,b) {
return a + b;
}
add(1,1);
add(1,2);

假设有1w个地方需要调用这个函数,你需要多写1w个1或2。后期如果要把1或2改成3的话,需要改1w个地方。上面的面向对象只需要在实例化的时候修改一下就可以了。

如果使用闭包呢?

function calc(num){
return function(a){ return a + num;}
}
addOne = calc(1);
addTwo = calc(2);
addOne(1); // 2
addTwo(2); // 3

是不是和上面的先定义了类,再实例化是一样的了?如果需要调整1或者2为3,只需要在构建闭包的时候调整一下就可以了。


最后再解释一下,为什么叫闭包呢?看上面的匿名函数!这个函数需要一个外部的变量num。当传递了num给它之后,它就不再需要直接访问外部的值了(只通过传入参数的方式获取值)。换种说法就是它对外关闭了!所以称为「闭包」!

如何才能通俗易懂的解释javascript里面的‘闭包’?

我是一名前端,无意间看见这个问题,我来回答一下!

我曾经写过一篇博客用来介绍闭包,谈不上通俗易懂,但是可以理解的比较深入!我个人认为理解闭包的概念的前提是理解作用域以及js的垃圾回收机制!


定义

作用域:变量和函数的可访问范围!

闭包:在某个作用域内定义的函数,它可以访问这个作用域内的所有变量!


从定义上看,我觉得闭包是函数作用域中一种现象,而且在es6之前,js只有函数级作用域,没有块级作用域,那么我们就来看看函数级作用域的特点!


函数级作用域

[[scope]]是所有父变量对象的层级链,处于当前函数上下文之上,在函数创建时存于其中。

全局上下文的变量对象是:

在getIdFac创建时,它的[[scope]]属性是:

在getIdFac执行时,其上下文的活动对象是:

getIdFac上下文的作用域链为:

内部函数cac创建时,其[[scope]]为:

在cac执行时,其上下文的活动对象为:

cac上下文的作用域链为:


内存管理

由于cac在包含它的函数外执行,对全局作用域中的变量x 和 父函数中y存在这个引用,所以呢,x和y所占的存储空间不会被回收!


综上,闭包存在于函数中,它是作用域的一种现象!


喜欢我的回答就关注我吧,有问题可以发表评论,我们一起学习,共同成长!

如何才能通俗易懂的解释javascript里面的‘闭包’?

简单通俗易懂的讲就是一个函数里面还有一个函数,然后这个内部函数里用到了外部函数的变量,这个内部函数就叫闭包。

概念通俗易懂,不过也得注意其用途。

它的最大用处有两个,一个是前面提到可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

简单解释下这两句话,我们在外部是无法访问到函数内部的变量的,如果我们想要访问,则可以通过在内部创建一个函数,也就是闭包来访问这个函数,然后通过外部函数返回这个闭包,那我们在外部就可以通过这个闭包来访问这个函数的内部变量了。

接着上面的情况,如果这个闭包我们赋值在一个全局变量上,那么这个闭包就保存在内存中,由于闭包访问了它外部函数的变量,所以又依赖于它的外部函数,这个外部函数也就保存在内存中,不会再调用结束后被垃圾回收机制回收。

如何才能通俗易懂的解释javascript里面的‘闭包’?

写一个最简单的闭包函数:

<script>

function fn1(){

var x = 10;

function fn2(){

alert(x);

}

return fn2; // 返回fn2的地址

}

var fn = fn1(); // 相当于fn指向了fn2的地址

fn(); // 执行fn2函数

</script>

解释:执行完var fn = fn1()的时候,fn1()会函数调用,去执行fn1的函数体,执行完毕之后,就会把fn1函数对象里的内部函数fn2函数对象的地址返回,按道理来说,fn1函数里面的局部变量x应该要被释放才对,但是由于fn2函数里面alert(x)用到了局部变量x,那么这个时候js引擎就不能把fn1函数对象进行垃圾回收,因为如果fn1函数对象被垃圾回收了,也就是意味着x变量就释放了,那么fn2函数对象里面还怎么能使用到x变量呢?而var fn = fn1(),其实就相当于fn变量指向了fn2函数对象的地址,既然是函数地址,那么就可以fn()函数调用,而fn2函数对象是在fn1函数内部,就说明fn1函数对象并不能被垃圾回收,这样也就是说外部可以访问一个函数内部的局部变量了。

闭包的作用:

1、可以访问一个函数的内部的变量

2、使此局部变量所占用的内存不被释放。

如何才能通俗易懂的解释javascript里面的‘闭包’?

最简单的理解,子程序里的子程序

留言与评论(共有 0 条评论)
   
验证码:
Top