2009-09-12 17 views
6

aşağıdaki JavaScript kodu göz önünde bulundurun:javascript kapatma anında değerlendirme

var a = []; 

var f = function() { 

    for (var i = 0; i < 3; i++) { 
     a.push(function(){alert(i)}); 
    } 
    for (var j = 0; j < 3; j++) { 
     a[j](); 
    } 
}; 

uyarıları çıktısını '3' her üç kez. Farklı bir davranış istiyoruz - döngünün her tekrarında i mevcut değerini yazar bir fonksiyonu oluşturur. Yani Farklı indeksler basan 3 fonksiyon.

Herhangi bir fikrin var mı? benzer

for (var i = 0; i < 3; i++) { 
    a.push((function(i) { 
     return function() { 
      alert(i); 
     } 
    })(i)); 
} 

for (var j = 0; j < 3; j++) { 
    a[j](); 
} 

Veya bilmediğimiz bir şey:

+0

Sadece bu eklemek için ... http://www.mattfreeman.co.uk/2010/03/closures-scope-in- olduğunu javascript-vs-c/ –

cevap

7

belirli işlevi parametre olarak i kabul eder ve döndüren isimsiz işlev oluşturun diziye işlevi eklemek için bir parametre olarak i kabul isimsiz işlev oluşturun:

for (var i = 0; i < 3; i++) { 
    (function(i) { 
     a.push(function() { 
      alert(i); 
     }); 
    })(i); 
} 

for (var j = 0; j < 3; j++) { 
    a[j](); 
} 
+1

Gerekli değil, ama sanırım daha temiz görünüyor ve "hemen çalıştırılan" işlevlerinizi "()" -> '(function (i) {...}) sarmak için niyetlerinizi daha iyi anlatıyor) (i) ' – gnarf

+0

@gnarf kendim bu tartışmaya. Sanırım amacı açıklığa kavuşturuyor. Bunu, – strager

+0

içinde düzenleyeceğim, bu, asıl problemi, aynı altta yatan kusurlara karşı duyarlı olmayan alternatif bir çözüm sunarak, yan basamak olarak görüyor görünmektedir ... Burada yaptığınız şey, bir diziye değerleri itmektir. Orijinal posteri, daha sonraki bir zamanda icra edileceğini düşündüğümüz fonksiyonları itiyor ... – Funka

1
var iterate = (function() { 
    var i, j = []; 
    for (i = 0; i < 3; i += 1) { 
     j.push(i); 
     alert(j[j.length - 1]); 
    } 
}()); 

Sen kapatılması sadece çıkış bir değer gerekmez. Kodunuz Ancak nesne yönelimli çevreleme için bir fonksiyonu yer almalıdır. Yürütülecek işlevlerin çağrılması gerekmez.

+0

"Yürütülecek işlevler aranmaz." Ne? Bu ifade çok açık değil ve yanlış olduğu için. Clarify, lütfen? – strager

+0

Bir işlevi yürütmek için üç şeyden biri gerçekleşmelidir. 1) İşlev, yürütmekte olan başka bir adla ada göre çağrılmalıdır. 2) İşlev bir yönteme eklenebilir, bu durumda işlev anonim olabilir ve yine de çalıştırılabilir. Fonksiyonları bir isim vermeden kullanmaya kesinlikle itiraz ediyorum. 3) Fonksiyonlar, kendi parantezleri ile sonlandırıldıkları takdirde, tamamen kendi başlarına çalışabilirler. Bu derhal çağrılı çağrılır. –

+0

Katılmıyorum. Bir işlev, Javascript'te "42" veya "merhaba dünya" gibi bir değer türüdür. Bir değişkene atanmış olsun ya da olmasın doğrudan özel bir şey anlamına gelmez. Bu davranışın bir örneği için şunu çalıştırın: '(function (i) {var func = arguments.callee; if (! I) döndürme; console.log ('x'); window.setTimeout (function() {func (i - 1);}, 1000);}) (4); ' – strager

-2

fonksiyonu (i) currying kullanarak {alert (i)

+2

Muhtemelen, undefined olacaktır. Farklılık için – strager

+0

+1. Bu, a.push (işlev (i) {alert (i)}) ise çalışır; , a.push yerine kullanılır (işlev() {alert (i)}); –

6

Bir başka yaklaşım,:

var a = []; 
var f = function() { 
    for (var i = 0; i < 3; i++) { 
     a.push((function(a){alert(a);}).curry(i)); 
    } 
    for (var j = 0; j < 3; j++) { 
     a[j](); 
    } 
}; 

// curry implementation 
Function.prototype.curry = function() { 
    var fn = this, args = Array.prototype.slice.call(arguments); 
    return function() { 
    return fn.apply(this, args.concat(
     Array.prototype.slice.call(arguments))); 
    }; 
}; 

Kontrol here çalışan yukarıdaki pasajı.

+1

Güzel köri kullanımı - şimdi açım olsa da .... – gnarf

+0

Vay. Bu harika. +1. – strager

0

Sen anonim işlevinde Döngünüzden gövdesini koyabilirsiniz: bu işlevi oluşturma ve "i" argüman olarak, yeni bir "i" değişkeni oluştururken ait döngünün değerini geçerek

var a = []; 

for(var i = 0; i < 3; i++) (function(i) { 
    a.push(function() { alert(i); }); 
})(i) 

for(var j = 0; j < 3; j++) { 
    a[j](); 
} 

esas olarak, dış "i" gizler döngü gövdesi içinde. Eğer dizinin üzerine itmek kapatma şimdi dış fonksiyon fonksiyonu ilk döngüde çağrıldığında ayarlanır değeri olan yeni bir değişken, görür.

var a = []; 

for(var i = 0; i < 3; i++) (function(iNew) { 
    a.push(function() { alert(iNew); }); 
})(i) 

for(var j = 0; j < 3; j++) { 
    a[j](); 
} 

"INEW" değeri fonksiyonu nedeniyle 2, sonra 1 sonra 0 atanır: Biz yeni bir değişken oluşturduğunuzda biz farklı bir ad kullanın, bu daha net olabilir ... Bu aynı şeyi yapar hemen döngü tarafından çağrılır. JavaScript blok kapsamı yalnızca işlev kapsamı kavramı yok nedeniyle, bu da beni atılmış çünkü