2013-04-22 1 views
0

пытается создать функции в test.tgt так же, как функции в test.src, за исключением того, что у них будет контекст.не может создать закрытие javascript

test.src.fn() => test.work.fn.call(context) 

здесь является испытательным полигоном

 
var fn1 = function() { console.log('fn1'); }; 
var fn2 = function() { console.log('fn2'); }; 
var context = { a: 1 }; 
var test = { 
    tgt: {}, 
    src: { one: fn1, two: fn2 }, 
    init: function() { 
    for(var i in test.src) { 
     test.tgt[i] = function(arg) { test.src[i].call(test.cxt,arg); }; 
    } 
    } 
} 
test.init(); 
test.src.one() => 'fn1' 
test.tgt.one() => 'fn2' ouch!! 

проблема заключается в том, что test.src[i] не вычисляется, пока функция не будет выполнена.

Как я могу получить «реальный» test.src[i] внутри вновь созданной функции?

+0

Возможный дубликат [Javascript закрытия внутри петель - простой практический пример] (http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) –

ответ

1

Все функции, созданные внутри init, имеют общее закрытие, поэтому они разделяют переменную i, поэтому она всегда является последней. Попробуйте это:

init: function() { 
    for(var i in test.src) { 
     (function(idx) { 
      test.tgt[idx] = function(arg) {test.src[idx].call(test.cxt,arg); }; 
     }(i)); 
    } 
} 
+0

", поэтому они делят i переменную , таким образом, это всегда последнее "- хорошее правило! У вас есть источник? –

+0

@ccyoung: https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures#Creating_closures_in_loops.3A_A_common_mistake –

2

Попытка создания закрытия для каждой итерации цикла:

var fn1 = function() { console.log('fn1'); }; 
var fn2 = function() { console.log('fn2'); }; 
var context = { a: 1 }; 
var test = { 
    tgt: {}, 
    src: { one: fn1, two: fn2 }, 
    init: function() { 
    for(var i in test.src) { 
     test.tgt[i] = (function(index){return function(arg) { test.src[index].call(test.cxt,arg); };}(i)); 
    } 
    } 
} 
test.init(); 
test.src.one() // => 'fn1' 
test.tgt.one() // => 'fn1' 
2

Это классический вопрос Javascript. Вы предполагаете, что i в контексте цикла for должен быть зафиксирован как значение, когда была создана функция, но вместо этого это последнее значение i. Чтобы обойти это, вы можете локально захватить его так:

test.tgt[i] = (function(local_i){ 
    return function(arg) { test.src[local_i].call(test.cxt,arg); }; 
})(i); 

Таким образом, вы заверните его в контексте функции, которая выполняется немедленно, а внутренняя функция получает правильное значение I для данной итерации.

Смежные вопросы