首页 > 编程知识 正文

js闭包的定义和用途,函数闭包的理解

时间:2023-05-05 20:43:21 阅读:48711 作者:718

js闭包到底是什么,这个问题一直让我很困惑,实在不明白,也不明白。

其实闭包是指在函数正在运行时,保存了应该释放的执行上下文对象(更准确地说,应该称为变量对象或活动对象),此时,该变量对象或活动对象

在更详细地理解概念理解闭包之前,让我们先理解以下几个概念。

1. 变量对象/活动对象

在执行函数时,将创建函数的执行上下文,函数的执行上下文包含变量对象,变量对象包含在正在执行的函数中定义的变量和函数,以及this、arguments、new.target等执行上下文事实上,存储在变量对象中的是我们的局部变量。 函数执行后,变量

2. 作用域和作用域链

范围是定义函数时生成的相对静态的概念。 我把这理解为静态范围链。 定义函数后,js将为此函数创建一个线性表(或数组或链表),以在定义函数时保存环境范围链的情况。 此环境中的范围链是一个动态概念,由运行时环境创建。 在浏览器中,可以打印函数对象。 您可以看到那里有“[[Scopes]]”属性。 此属性无法从外部访问。 其中存储的是上述函数定义时环境的动态范围链的情况。 定义函数后,此属性保持不变。 这就是为什么作用域是静态的

您为顶级范围(窗口对象)定义了函数outer。 console.dir ) )打印时,浏览器可以看到此属性。 由于outer是在顶级范围中定义的,因此在定义outer时,动态范围链中只有一个窗口对象,因此在[scoper]全局环境中,动态范围链中只有一个对象

3. 函数执行中动态作用域链的创建过程

首先执行函数时,会创建函数的执行上下文,然后初始化执行上下文,如等待this对象、arguments对象的创建。 这些变量将添加到执行函数的变量对象中。 当然,最重要的是在函数运行时创建范围链。 这是一个动态范围链,与上述函数定义时的静态范围链有关,但不同。 该动态范围链首先提取函数的静态范围链,即函数定义时的“[[Scopeds]]”属性作为初始化的动态范围链,然后运行函数的变量对象插入该动态范围链的开头,位于顶层这将在此范围链上搜索函数中的变量标识符,并搜索到最底层的范围

闭包对象的生成在上面解释了一些概念,但重点是理解静态范围链与动态范围链的关系,以及什么是变量对象。 回到正题。 我们想说明的是闭包。 那么,闭包是怎么产生的呢? 假设您在全局范围中定义了outer函数。 此函数的“[[Scopes]]”属性有哪些? 如上所述,其中只有一个对象,也就是全局变量对象。 当这个outer函数运行时,动态范围链是什么样的呢? 如前所述,将函数的[[Scopes]]初始化为动态范围链,并将当前函数的变量对象插入此动态范围链的开头,即可形成此函数环境中的动态范围链。 那么,如果为outer函数定义另一个函数inner,您可能会想,inner的“[scopes]”属性是什么? 是当前环境的动态范围链。 也就是说,包含两个对象的路线表。 第一个对象是outer函数的变量对象,第二个对象是全局变量对象。 如果将inner函数作为outer函数的返回值,则会发生奇怪的事情。 看看这个流程吧。 执行outer函数后,返回inner函数。 此时,对于outer函数,该变量对象应该在函数执行后被废弃,但是此时的inner函数被返回并保存在变量中,而且由于inner函数的[[Scopes]]属性中有对outer变量对象的引用。 这是闭包的形成,将outer的变量对象称为3330,其实闭包是对象,是其外部函数的变量对象。 执行外部函数后,如果保留了内部函数,则外部函数的变量对象会保留在内部函数的[[Scopes]]属性中,外部函数的变量对象不会丢弃,从而形成闭包。

最后,让我们看看这个代码

function outer ({ leta=' 123 ' returnfunctioninner ) } { console.log } } let inner function=outer ) ) console.diidition

此innerFunction的“[[Scopes]]”属性有两个对象:定义时外部函数outer的变量对象和调用inner函数时创建的全局变量对象

链中就会有这两个对象,加上inner函数自己的变量对象,所以在函数inner执行的过程中为什么能访问到定义时外层函数outer中的变量,就是因为这个原因,我们从图中可以看到,outer函数的变量对象前面被标注了一个Closure(闭包),说明outer函数的变量对象此时是一个闭包对象。

总结

所以讲了这么多,是不是发现闭包其实没什么,就是一个函数运行时的变量对象,只是这个对象没有在正确的时间被销毁而已,从文字层面,闭包的意思就是将一个东西关闭起来,这个被关闭的东西就是外层函数的变量对象,我们让它不被销毁,所以叫闭包。总的来说,闭包是js实现函数嵌套函数定义的核心,这是js对实现嵌套定义必然产生的一种效果,也相当于是一种副作用,如果js引擎不这么做,那么就没办法保存函数的作用域链。现在js引擎对闭包是有优化的,它会尽可能的回收没用的变量,也就是说,闭包对象中只会存在内层函数所引用的变量,而那些没有被内层函数引用的变量,js引擎会将它们释放。

以上便是个人在学习过程中对于闭包的理解,如果发现我对闭包的理解有任何问题,请各位整齐的月饼们指出,谢谢大家。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。