循环内的JavaScript闭包–;简单实例

循环内的JavaScript闭包–;简单实例,javascript,loops,closures,Javascript,Loops,Closures,var funcs=[]; //让我们创建3个函数 对于(变量i=0;i

var funcs=[];
//让我们创建3个函数
对于(变量i=0;i<3;i++){
//并将其存储在funcs中
funcs[i]=函数(){
//每个都应记录其值。
console.log(“我的值:+i”);
};
}
对于(var j=0;j<3;j++){
//现在让我们每个人都来看看
funcs[j]();
}
试试:

var funcs=[];
对于(变量i=0;i<3;i++){
funcs[i]=(函数(索引){
返回函数(){
log(“我的值:+索引”);
};
}(i) );
}
对于(var j=0;j<3;j++){
funcs[j]();
}
试试:

var funcs=[];
对于(变量i=0;i<3;i++){
funcs[i]=(函数(索引){
返回函数(){
log(“我的值:+索引”);
};
}(i) );
}
对于(var j=0;j<3;j++){
funcs[j]();

}
问题是,每个匿名函数中的变量
i
都绑定到函数外部的同一个变量

ES6解决方案:
let
ECMAScript 6(ES6)引入了新的
let
const
关键字,这些关键字的作用域不同于基于
var
的变量。例如,在一个基于
let
索引的循环中,循环中的每个迭代都将有一个具有循环范围的新变量
i
,因此代码将按预期工作。有很多资源,但我推荐它作为一个很好的信息来源

for (let i = 0; i < 3; i++) {
  funcs[i] = function() {
    console.log("My value: " + i);
  };
}
其思想是,与
.forEach
循环一起使用的回调函数的每次调用都将是它自己的闭包。传递给该处理程序的参数是特定于迭代特定步骤的数组元素。如果在异步回调中使用,它将不会与在迭代的其他步骤中建立的任何其他回调冲突

如果您碰巧在jQuery中工作,
$。each()
函数为您提供了类似的功能


经典解决方案:闭包 您要做的是将每个函数内的变量绑定到函数外的一个单独的、不变的值:

function makeHelper(obj)
{
  return {
    inc: function(){obj.counter++;},
    get: function(){return obj.counter;}
  }; 
}

function makeCounters(num)
{
  for (var i = 0; i < num; i++)
  {
    var obj = {counter: 0};
    counters[i] = makeHelper(obj);
  }
}
var funcs = [];
function tempFunc(i){
    return function(){
        console.log("My value: " + i);
    };
}
for (var i = 0; i < 3; i++) {  
    funcs[i] = tempFunc(i);                                     
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        
}
var funcs=[];
函数createfunc(i){
返回函数(){
console.log(“我的值:+i”);
};
}
对于(变量i=0;i<3;i++){
funcs[i]=createfunc(i);
}
对于(var j=0;j<3;j++){
//现在让我们每个人都来看看
funcs[j]();

}
问题是,每个匿名函数中的变量
i
都绑定到函数外部的同一个变量

ES6解决方案:
let
ECMAScript 6(ES6)引入了新的
let
const
关键字,这些关键字的作用域不同于基于
var
的变量。例如,在一个基于
let
索引的循环中,循环中的每个迭代都将有一个具有循环范围的新变量
i
,因此代码将按预期工作。有很多资源,但我推荐它作为一个很好的信息来源

for (let i = 0; i < 3; i++) {
  funcs[i] = function() {
    console.log("My value: " + i);
  };
}
其思想是,与
.forEach
循环一起使用的回调函数的每次调用都将是它自己的闭包。传递给该处理程序的参数是特定于迭代特定步骤的数组元素。如果在异步回调中使用,它将不会与在迭代的其他步骤中建立的任何其他回调冲突

如果您碰巧在jQuery中工作,
$。each()
函数为您提供了类似的功能


经典解决方案:闭包 您要做的是将每个函数内的变量绑定到函数外的一个单独的、不变的值:

function makeHelper(obj)
{
  return {
    inc: function(){obj.counter++;},
    get: function(){return obj.counter;}
  }; 
}

function makeCounters(num)
{
  for (var i = 0; i < num; i++)
  {
    var obj = {counter: 0};
    counters[i] = makeHelper(obj);
  }
}
var funcs = [];
function tempFunc(i){
    return function(){
        console.log("My value: " + i);
    };
}
for (var i = 0; i < 3; i++) {  
    funcs[i] = tempFunc(i);                                     
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        
}
var funcs=[];
函数createfunc(i){
返回函数(){
console.log(“我的值:+i”);
};
}
对于(变量i=0;i<3;i++){
funcs[i]=createfunc(i);
}
对于(var j=0;j<3;j++){
//现在让我们每个人都来看看
funcs[j]();

}
原始示例不起作用的原因是,在循环中创建的所有闭包都引用了同一帧。实际上,在一个对象上有3个方法,并且只有一个
i
变量。它们都输出了相同的值。

原始示例不起作用的原因是,在循环中创建的所有闭包都引用了相同的帧。实际上,在一个对象上有3个方法,并且只有一个
i
变量。它们都输出了相同的值。

您需要了解的是javascript中变量的范围是基于函数的。这与使用块作用域的c#相比是一个重要的区别,只需将变量复制到for中的一个即可

将其包装在一个函数中,该函数将像apphacker的答案那样返回函数,因为变量现在具有函数作用域

还有一个let关键字而不是var,这将允许使用块范围规则。在这种情况下,在for中定义一个变量就可以了。也就是说,由于兼容性,let关键字不是一个实用的解决方案

var funcs={};
对于(变量i=0;i<3;i++){
让index=i;//添加这个
funcs[i]=函数(){
log(“我的值:+索引);//更改为副本
};
}
对于(var j=0;j<3;j++){
funcs[j]();

}
您需要了解的是javascript中变量的范围是基于函数的。这与使用块作用域的c#相比是一个重要的区别,只需将变量复制到for中的一个即可

将其包装在一个函数中,该函数将像apphacker的答案那样返回函数,因为变量现在具有函数作用域

还有一个let关键字而不是var,这将允许使用块范围规则。在这种情况下,在for中定义一个变量就可以了。也就是说,由于兼容性,let关键字不是一个实用的解决方案

var funcs={};
为了(
var funcs = [];
for(var new_i =0; new_i<3; new_i++){
    (function(i){
        funcs[i] = function(){
            alert(i);
        }
    })(new_i);
}

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

function createfunc(i) {
    return function(){console.log("My value: " + i);};
}
funcs[i] = function() {            // and store them in funcs
    throw new Error("test");
    console.log("My value: " + i); // each should log its value.
};
funcs[i] = new function() {   
    var closedVariable = i;
    return function(){
        console.log("My value: " + closedVariable); 
    };
};
funcs = {};
for (var i = 0; i < 3; i++) {         
  funcs[i] = function inner() {        // function inner's scope contains nothing
    console.log("My value: " + i);    
  };
}
console.log(window.i)                  // test value 'i', print 3
funcs = {};
function outer(i) {              // function outer's scope contains 'i'
  return function inner() {      // function inner, closure created
   console.log("My value: " + i);
  };
}
for (var i = 0; i < 3; i++) {
  funcs[i] = outer(i);
}
console.log(window.i)          // print 3 still
[0,2,3].forEach(function(i){ console.log('My value:', i); });
// My value: 0
// My value: 2
// My value: 3
var funcs = Query.range(0,3).each(function(i){
     return  function() {
        console.log("My value: " + i);
    };
});
funcs.iterate(function(f){ f(); });
var funcs = [];

new Array(3).fill(0).forEach(function (_, i) { // creating a range
    funcs[i] = function() {            
        // now i is safely incapsulated 
        console.log("My value: " + i);
    };
});

for (var j = 0; j < 3; j++) {
    funcs[j](); // 0, 1, 2
}
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
}
var funcs = [];
for (var i = 0; i < 3; i++) {          
    let index = i;
    funcs[i] = function() {            
        console.log("My value: " + index); 
    };
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        
}
var funcs = [];
function tempFunc(i){
    return function(){
        console.log("My value: " + i);
    };
}
for (var i = 0; i < 3; i++) {  
    funcs[i] = tempFunc(i);                                     
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        
}
Create variable `funcs` and assign it an empty array;  
Loop from 0 up until it is less than 3 and assign it to variable `i`;
    Push to variable `funcs` next function:  
        // Only push (save), but don't execute
        **Write to console current value of variable `i`;**

// First loop has ended, i = 3;

Loop from 0 up until it is less than 3 and assign it to variable `j`;
    Call `j`-th function from variable `funcs`:  
        **Write to console current value of variable `i`;**  
        // Ask yourself NOW! What is the value of i?
var funcs = [];
for (var i = 0; i < 3; i++) {          // let's create 3 functions
    funcs[i] = function(x) {            // and store them in funcs
        console.log("My value: " + x); // each should log its value.
    }.bind(null, i);
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}
var funcs = [];
for (let 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 (let j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}
var funcs = [];
for (var i = 0; i < 3; i++) {     
  (funcs[i] = function() {         
    console.log("My value: " + i); 
  })(i);
}
var funcs = [];
for (var i = 0; i < 3; i++) {      // let's create 3 functions
  funcs[i] = curryShowValue(i);
}
for (var j = 0; j < 3; j++) {
  funcs[j]();                      // and now let's run each one to see
}

function curryShowValue(i) {
  return function showValue() {
    console.log("My value: " + i);
  }
}
<script>
   var funcs = [];
   for (var i = 0; i < 3; i++) {
     funcs[i] = function () {
        debugger;
        console.log("My value: " + i);
     };
   }
   console.log(funcs);
</script>
<script>
    var funcs = [];
    for (let i = 0; i < 3; i++) {
        funcs[i] = function () {
           debugger;
           console.log("My value: " + i);
        };
    }
    console.log(funcs);
</script>