欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > 闭包遇到的问题

闭包遇到的问题

2024/10/25 0:36:38 来源:https://blog.csdn.net/BHDDGT/article/details/141899087  浏览:    关键词:闭包遇到的问题

闭包是指在一个函数内部定义的函数能够“记住”其所在的词法作用域,即使这个外部函数已经执行完毕。这意味着内部函数可以访问外部函数的变量,即使外部函数已经结束。重点是思想是:函数内部定义的函数可以访问外部函数的变量

举个例子,代码如下

function outerFunction() {let outerVar = 'I am outside!';function innerFunction() {console.log(outerVar);  // 访问外部函数的变量}return innerFunction;
}const inner = outerFunction();
inner(); // 这会输出 'I am outside!'

在这个例子中,innerFunction 是在 outerFunction 内部定义的,并且它能够访问 outerFunction 中定义的 outerVar 变量。即使 outerFunction 执行完毕并返回后,innerFunction 仍然“记住”了 outerVar 的值,这就是闭包的特性

下面来分析一下实际项目中遇到的有关闭包的问题,代码如下(因为是直接从项目里截取出来的,所以格式有些问题)

            selectGroups.forEach(group => {// 每个组里面副标题只会有一个secondsTitle = group.querySelector('.arrow-right');// 让当前循环到的副标题展示出来secondsTitle.classList.toggle('allowAll'); console.log(secondsTitle);  // 给所有副标题添加点击事件// 点击副标题展示当前副标题下的子内容secondsTitle.addEventListener('click',()=>{secondsTitle.classList.toggle('arrow-right'); secondsTitle.classList.toggle('arrow-top');console.log(secondsTitle);items = group.querySelector('.select-items');items.classList.toggle('allowAll');});})

首先结构是循环每个selectGroups,每个selectGroups里都有一个secondsTitle,希望为当前这个secondsTitle添加点击事件。遇到的问题是,在当前只有两个selectGroup的情况下,每次点打印出来的都是第二个selectGroup里的secondsTitle。

排查了一会发现了问题所在。准确来说,问题是每次打印出来的都是最后一个selectGroup里的secondsTitle,也就是说每次循环的secondsTitle被覆盖,导致只有最后一个点击事件有效果。

我的理解:我看不出来有问题,理解中每一层循环secondsTitle,然后分别给当前secondsTitle添加点击事件,接下来一步步分析。

首先,secondsTitle没有定义,js引擎解析secondsTitle变量的时候,因为没有在当前作用域中找到相关声明,那么会向上寻找父级作用域直到全局作用域,如果还是没有就默认为全局变量var。

接下来,要知道闭包这个概念,前面已经说了它的一个特点,接下来是另一个特点,闭包会“记住”其所在的词法作用域中的变量引用,而不是变量的值。使用var声明的是全局变量,每次secondsTitle = group.querySelector('.arrow-right')实际上只改变了这个变量的值而没有改变引用,可以理解为在循环中给每个按钮(secondsTitle)分配了一个标记(点击事件)。但由于 var 的作用域特性,这些标记都指向同一个记号(secondsTitle 变量)。每次你循环时,记号上的内容(即变量的值)会被擦掉并写上新的内容,那么最后,只会有一个按钮,并且按钮上面的内容只会是最后一个循环到的文本,而不是预想中的每一个文本有一个按钮。

解决方法:为了让每个闭包捕获独立的变量,可以使用 let,因为它是块级作用域,每次循环都会创建一个独立的变量实例,闭包捕获的就是不同的变量引用,结合上面的例子思考就是创建了新按钮,并填写了当前文本,符合预期。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com