问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

什么是JavaScript闭包

发布网友 发布时间:2022-05-15 08:55

我来回答

2个回答

懂视网 时间:2022-05-15 13:16

举一个例子:

function test(){
 var a = 1;
 var b = function(){
 return a; 
 };
 return b;
}

var c = test();
console.log(c()); //1

这里c是直接得到了b这个函数表达式,但是调用c之后可以得到test的局部变量a的值1,也就是c它访问到了test作用域中的变量。
其实我初学的时候一直不清楚闭包的意思,因为我感觉这种情况是理所当然的,噗,后来才知道原来就是说这个啊。

为什么会产生闭包

究其根本,是因为b代表的函数包含test的作用域。
在某个函数被调用时会做下面这些事:

  1. 创建一个执行环境。

  2. 创建相应的作用域链(复制函数的[[Scope]]来完成)。

  3. 初始化函数的活动对象(arguments和其他命名参数),并被推入作用域最顶端。

而在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象处于第三位...直到作为作用域链终点的全局执行环境。

举个栗子

function test(value1,value2){
 if(value1 < value2)
 return -1;
 return 0;
}
var result = test(5,10);

以上首先定义了test函数,又在全局作用域中调用它。
第一次调用时,会创建一个包含this、arguments、value1和value2的活动对象。
全局执行环境的变量(this、result、test)则处于test执行环境作用域链中的第二位。

每个执行环境都有一个表示变量的对象,称为变量对象。
全局环境的变量对象一直存在,test()函数局部环境的变量对象只有在执行的时候会存在。

函数的作用域链是保存在内部的[[Scope]]属性中。
作用域本质是一个指针列表,只保存引用。
以下是最初的栗子中test()的原型内容:

匿名函数执行结束后,它的执行环境被销毁了,但是返回的活动对象没有消失,所以闭包也不会消失,依旧存在内存中,如果给这个对象赋值null,就可以解除关系。

原来如此

让我们瞅瞅这段熟悉的代码:

function test(){
 var result = new Array();
 for(var i=0;i<10;i++){
 result[i] = function(){
  return i;
 }
 }
 return result;
}

这个函数的实际结果是每个函数都返回了10,因为它们实际的i都是同一个。
解决方法是用匿名函数:

function test(){
 var result = new Array();
 for(var i=0;i<10;i++){
 result[i] = function(num)(
  return function(){
  return num;
  }
 }(i);
 }
 return result;
}

由于中间多加上了一层,即每次把一个num值传入,所以内部的函数是形成了各自num的闭包,于是就没有像之前一样共用了。

热心网友 时间:2022-05-15 10:24

一、什么是闭包?
“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
相信很少有人能直接看懂这句话,因为他描述的太学术。我想用如何在Javascript中创建一个闭包来告诉你什么是闭包,因为跳过闭包的创建过程直接理解闭包的定义是非常困难的。看下面这段代码:
function a(){
var i=0;
function b(){
alert(++i);
}
return b;
}
var c = a();
c();
这段代码有两个特点:
1、函数b嵌套在函数a内部;
2、函数a返回函数b。
这样在执行完var c=a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说:

当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。

我猜想你一定还是不理解闭包,因为你不知道闭包有什么作用,下面让我们继续探索。

二、闭包有什么作用?
简而言之,闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。这是对闭包作用的非常直白的描述,不专业也不严谨,但大概意思就是这样,理解闭包需要循序渐进的过程。
在上面的例子中,由于闭包的存在使得函数a返回后,a中的i始终存在,这样每次执行c(),i都是自加1后alert出i的值。

那 么我们来想象另一种情况,如果a返回的不是函数b,情况就完全不同了。因为a执行完后,b没有被返回给a的外界,只是被a所引用,而此时a也只会被b引 用,因此函数a和b互相引用但又不被外界打扰(被外界引用),函数a和b就会被GC回收。(关于Javascript的垃圾回收机制将在后面详细介绍)

三、闭包内的微观世界
如 果要更加深入的了解闭包以及函数a和嵌套函数b的关系,我们需要引入另外几个概念:函数的执行环境(excution context)、活动对象(call object)、作用域(scope)、作用域链(scope chain)。以函数a从定义到执行的过程为例阐述这几个概念。

1、当定义函数a的时候,js解释器会将函数a的作用域链(scope chain)设置为定义a时a所在的“环境”,如果a是一个全局函数,则scope chain中只有window对象。
2、当函数a执行的时候,a会进入相应的执行环境(excution context)。
3、在创建执行环境的过程中,首先会为a添加一个scope属性,即a的作用域,其值就为第1步中的scope chain。即a.scope=a的作用域链。
4、然后执行环境会创建一个活动对象(call object)。活动对象也是一个拥有属性的对象,但它不具有原型而且不能通过JavaScript代码直接访问。创建完活动对象后,把活动对象添加到a的作用域链的最顶端。此时a的作用域链包含了两个对象:a的活动对象和window对象。
5、下一步是在活动对象上添加一个arguments属性,它保存着调用函数a时所传递的参数。
6、最后把所有函数a的形参和内部的函数b的引用也添加到a的活动对象上。在这一步中,完成了函数b的的定义,因此如同第3步,函数b的作用域链被设置为b所被定义的环境,即a的作用域。

到此,整个函数a从定义到执行的步骤就完成了。此时a返回函数b的引用给c,又函数b的作用域链包含了对函数a的活动对象的引用,也就是说b可以访问到a中定义的所有变量和函数。函数b被c引用,函数b又依赖函数a,因此函数a在返回后不会被GC回收。

当函数b执行的时候亦会像以上步骤一样。因此,执行时b的作用域链包含了3个对象:b的活动对象、a的活动对象和window对象,如下图所示:

如图所示,当在函数b中访问一个变量的时候,搜索顺序是先搜索自身的活动对象,如果存在则返回,如果不存在将继续搜索函数a的活动对象,依 次查找,直到找到为止。如果整个作用域链上都无法找到,则返回undefined。如果函数b存在prototype原型对象,则在查找完自身的活动对象 后先查找自身的原型对象,再继续查找。这就是Javascript中的变量查找机制。

四、闭包的应用场景
1、保护函数内的变量安全。以最开始的例子为例,函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。
2、在内存中维持一个变量。依然如前例,由于闭包,函数a中i的一直存在于内存中,因此每次执行c(),都会给i自加1。
以上两点是闭包最基本的应用场景,很多经典案例都源于此。

五、Javascript的垃圾回收机制
在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
天将雄师观后感600字 为什么喝酒会降血糖 牛栏山 52度浓香型白酒-购买最佳价格 全兴大曲 52度浓香型白酒-购买最佳价格 笔记本电脑怎么接音箱电脑如何连接外置音箱 笔记本电脑有音箱插孔吗笔记本电脑如何连接喇叭 冰箱压缩机过热启动5秒就停了 周长相等的正方形和圆,其面积比是多少 周长相等的正方形和圆面积比是多少 周长相等的正方形与圆形,边长与半径的比是( ),面积之比是( )。 要有... 袁隆平爷爷为我们做了很多,什么是我们能够为袁隆平做的? 袁老与袁花花的初见视频曝光,袁花花到底是谁? 袁隆平获荣誉勋章,90岁的袁爷爷为何会快乐得像个孩子? 袁爷爷遗体上覆盖着鲜红的国旗,有什么深刻寓意? 袁隆平曾用小提琴演奏《我的祖国》,袁爷爷还是位艺术家吗? 袁隆平院士开通抖音系公司蓄意博眼球,袁爷爷为何能够一天内吸粉千万? 外媒为袁隆平集体刷屏,袁爷爷的影响力到底有多大? 袁隆平爷爷诞辰91周年,他的一生有多传奇? 袁隆平爷爷为什么被称为世界杂交水稻之父? 韩国代购都有什么东西,电子产品可以吗 袁隆平77岁曾走遍上海超级稻农田,在你心目中袁爷爷是个怎样的人物? 造福人类的袁爷爷,他做的贡献有多大? 什么是韩国代购啊? 什么是韩国代购?质量有保证吗 一种石头越戴越红是什么石头呢 黃龙玉里有红色黄色灰色金沙很多这样的黄龙玉是什么级别的 表面桔黄色的玉器应该叫什么玉? 这到底是什么石头,谁能给个确切回答。 白云石玉的介绍 怎么看黄龙玉的成色啊 看完《火影忍者》后发现好多人讨厌春野樱,仅仅是因为小时候对鸣人不好吗? 春野樱为什么被众多的火影迷讨厌呢? 春野樱的档案 《火影忍者》春野樱为什么那么让人讨厌? 动漫中有哪些角色,虽然大家都喜欢但是你很讨厌的呢? 《火影忍者》中,木叶众女神的颜值巅峰时刻是在什么时候呢? 春野樱小时候是哪一集 应该蛮长的时间吧 樱花大战 春野樱的资料 小樱(木之本)的资料,越具体月好,最好有小樱里所有认得资料!!!!!!!! 山中井野和春野樱是怎么认识的 火影忍者疾风传中小樱小时候是多少集 王卡助手充话费 为什么会出来微保? 腾讯王卡微保校园礼包活动介绍? 王卡充值总是弹出微保怎么办? 腾讯王卡微保校园礼包活动参与方式? 用王卡助手充话费怎么转到微保保证金上去了? 微保校园礼包上架王卡福利社限时活动如何参与? 腾讯王卡微保校园礼包活动权益有哪些? 申请的大王卡人工审核通过,上门订单等待同步码上购,在王卡助手查的,显示这个是什么意思, bai白色的毛毛领子给其他的衣服洗黑了怎么恢复白色的怎么能恢复白色的?