JavaScript匿名自执行函数以及闭包问题

总结下最近在写的项目中遇到的一个小问题:

Mutable variable is accessible from closure

问题的解决办法涉及到 JavaScript 的闭包匿名自执行函数,关于什么是闭包并不像知乎上各位大神的“通俗解释”那样难理解,看一篇方应行的JS中的闭包是什么?就足够了。接下来,详细说说我所遇到的问题及解决办法

我在项目中写了下面这段代码:

mark

这段代码的目的是使用循环给多个元素绑定点击事件,看起来好似完全没问题,但测试时却发现并没有成功给元素绑定点击事件,这时我注意到了在 IDEA 回调函数中的变量 i 颜色和其他的 i 颜色不同,鼠标悬浮在该变量上, IDEA 提示如下:

Mutable variable is accessible from closure.
Checks for accessing mutable JavaScript variables in nested function. The validation works in JavaScript, html, or jsp files.

重点在第一句,意思就是在提示我们循环变量 i 可以从 闭包 中访问,这个提示看的我一脸茫然,但最终在 Stack Overflow上找到了答案:

Mutable variable is accessible from closure
How to avoid access mutable variable from closure
Mutable variable is accessible from closure. How can I fix this?

原来是因为我绑定的回调函数只有在点击元素时才会调用,而此时 for 循环早已执行完毕,回调函数中并没有拿到循环中正确的变量 i,也就是说我遇到了循环和异步调用的经典问题,同时这也是闭包的经典作用之一

解决办法是使用闭包来保存变量,这样即使 i一直在变,但闭包中使用 index 变量保存了变量 i 的值,回调函数就可以拿到正确的下标了,所以,最终我把代码改成了如下形式

function clickImageIcon(msgArr, options) {

for (var i = 0; i < msgArr.length; i ++) {

(function() {
    
    var index = i;

    $('.file-wrapper:eq(' + index + ')').bind('click', function () {

        recognitionContent(msgArr[index]);

        $('#myModal').modal(options);

    });

   })();

}

}

当然为了传参你也可以把匿名自执行函数写成如下形式,详见js中的匿名函数和匿名自执行函数

function clickImageIcon(msgArr, options) {

for (var i = 0; i < msgArr.length; i ++) {

(function(index) {

$('.file-wrapper:eq(' + index + ')').bind('click', function () {

recognitionContent(msgArr[index]);

$('#myModal').modal(options);

});

})(i);

}

}

 

如果你使用 ES6,使用 let 代替 var 也是OK的:

function clickImageIcon(msgArr, options) {

for (let i = 0; i < msgArr.length; i ++) {

$('.file-wrapper:eq(' + i + ')').bind('click', function () {

recognitionContent(msgArr[i]);

$('#myModal').modal(options);

});

}

}

至于为什么 let 代替 var 就能解决这个问题,我在 V2EX 上提了相应的问题,想要了解的请移步JavaScript let 关键字问题求解,总结来说就是 var 是函数级作用域,而 let 是块级作用域,所以 let 能起到和闭包相同的效果

另外 V2EX 上也有人提到 bind 函数的第二个参数就是子元素,所以下面的代码也可以:

function clickImageIcon(msgArr, options) {

for (var i = 0; i < msgArr.length; i ++) {

$('.file-wrapper:eq(' + i+ ')').bind('click', i, function (e) {

recognitionContent(msgArr[e.data]);

$('#myModal').modal(options);

});

}

}

本文标题:JavaScript匿名自执行函数以及闭包问题

文章作者:KURANADO

发布时间:2018-03-20, 16:01:00

最后更新:2018-03-20, 16:03:41

原始链接:http://www.kuranado.com/2018/03/20/JavaScript匿名自执行函数以及闭包问题/

猜你喜欢

转载自blog.csdn.net/qq_25987491/article/details/82120023