JavaScript闭环内循环 - 简单的实例 [英] JavaScript closure inside loops – simple practical example

查看:201
本文介绍了JavaScript闭环内循环 - 简单的实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

var funcs = [];
for (var i = 0; i < 3; i++) {          // let's create 3 functions
    funcs[i] = function() {            // and store them in funcs
        console.log("My value: " + i); // each should log its value.
    };
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}

p>

It outputs this:


我的值:3

我的值:3

我的值:3

My value: 3
My value: 3
My value: 3

我想输出:


我的值:0

我的值:1

我的值:2

My value: 0
My value: 1
My value: 2

解决方案这个基本问题?

What's the solution to this basic problem?

推荐答案

好吧,问题是变量 i ,在每个匿名函数中,绑定到函数外的同一个变量。

Well, the problem is that the variable i, within each of your anonymous functions, is bound to the same variable outside of the function.

你想做的是在每个函数中绑定变量到函数之外的单独的,不变的值:

What you want to do is bind the variable within each function to a separate, unchanging value outside of the function:

var funcs = [];

function createfunc(i) {
    return function() { console.log("My value: " + i); };
}

for (var i = 0; i < 3; i++) {
    funcs[i] = createfunc(i);
}

for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}

在JavaScript - 只有函数范围 - 通过在新函数中包装函数创建,确保i的值保持原样。

Since there is no block scope in JavaScript - only function scope - by wrapping the function creation in a new function, you ensure that the value of "i" remains as you intended.

更新:相对广泛的 Array.prototype.forEach 功能(2015年),值得注意在那些主要通过值数组进行迭代的情况下, .forEach()提供了一种干净,自然的方式来为每次迭代获得一个明确的闭包。也就是说,假设你有一些数组包含值(DOM引用,对象,无论什么),并且设置特定于每个元素的回调的问题,你可以这样做:

Update: with the relatively widespread availability of the Array.prototype.forEach function (in 2015), it's worth noting that in those situations involving iteration primarily over an array of values, .forEach() provides a clean, natural way to get a distinct closure for every iteration. That is, assuming you've got some sort of array containing values (DOM references, objects, whatever), and the problem arises of setting up callbacks specific to each element, you can do this:

var someArray = [ /* whatever */ ];
// ...
someArray.forEach(function(arrayElement) {
  // ... code code code for this one element
  someAsynchronousFunction(arrayElement, function() {
    arrayElement.doSomething();
  });
});

想法是每次调用与 .forEach loop将会是它自己的闭包。传递给该处理程序的参数是特定于迭代的特定步骤的数组元素。如果它在异步回调中使用,它不会与在其他迭代步骤建立的任何其他回调冲突。

The idea is that each invocation of the callback function used with the .forEach loop will be its own closure. The parameter passed in to that handler is the array element specific to that particular step of the iteration. If it's used in an asynchronous callback, it won't collide with any of the other callbacks established at other steps of the iteration.

如果你碰巧使用jQuery , $。each()函数给你一个类似的能力。

If you happen to be working in jQuery, the $.each() function gives you a similar capability.

Update 2: strong>
ECMAScript 6(ES6)是JavaScript的最新版本,现在开始在许多常绿的浏览器和后端系统中实现。还有像 Babel 这样的转换器,可将ES6转换为ES5,以允许在旧系统上使用新功能。

Update 2: ECMAScript 6 (ES6), the newest version of JavaScript, is now starting to be implemented in many evergreen browsers and backend systems. There are also transpilers like Babel that will convert ES6 to ES5 to allow usage of new features on older systems.

ES6引入了新的 let const 关键字 var 的变量。例如,在具有 let 的索引的循环中,每个循环的迭代将有一个新的值 i 其中每个值的范围在循环内,所以你的代码将如你所期望的那样工作。有许多资源,但我会建议 2ality的封锁范围的帖子作为一个伟大的信息来源。

ES6 introduces new let and const keywords that are scoped differently than var-based variables. For example, in a loop with a let-based index, each iteration through the loop will have a new value of i where each value is scoped inside the loop, so your code would work as you expect. There are many resources, but I'd recommend 2ality's block-scoping post as a great source of information.

for (let i = 0; i < 3; i++) {
    funcs[i] = function() {
        console.log("My value: " + i);
    };
}

这篇关于JavaScript闭环内循环 - 简单的实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆