D├Âng├╝ler i├žinde JavaScript kapat─▒lmas─▒ - basit pratik ├Ârnek


Al─▒nan cevaba git


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

Bu ├ž─▒kt─▒:

De─čerim: 3
De─čerim: 3
De─čerim: 3

Oysa ├ž─▒kt─▒ olmas─▒n─▒ isterdim:

De─čerim: 0
De─čerim: 1
De─čerim: 2


Ayn─▒ sorun, i┼člevi ├žal─▒┼čt─▒rmadaki gecikmenin olay dinleyicileri kullan─▒lmas─▒ndan kaynaklanmas─▒ durumunda ortaya ├ž─▒kar:

 var buttons = document.getElementsByTagName("button");
// let's create 3 functions
for (var i = 0; i < buttons.length; i++) {
  // as event listeners
  buttons[i].addEventListener("click", function() {
    // each should log its value.
    console.log("My value: " + i);
  });
} 
 <button>0</button>
<br />
<button>1</button>
<br />
<button>2</button> 

ÔÇŽ Veya e┼čzamans─▒z kod, ├Ârne─čin Promises kullanarak:

 // Some async wait function
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));

for (var i = 0; i < 3; i++) {
  // Log `i` as soon as each promise resolves.
  wait(i * 100).then(() => console.log(i));
} 

Bu temel sorunun ├ž├Âz├╝m├╝ nedir?


2667









Cevap say─▒s─▒n─▒ say: 30






Sorun ┼ču ki, i ads─▒z i┼člevlerinizin her birinin i├žindeki de─či┼čken , i┼člev d─▒┼č─▒ndaki ayn─▒ de─či┼čkene ba─čl─▒.

Klasik ├ž├Âz├╝m: Kapaklar

Yapmak istedi─činiz, her fonksiyonun i├žindeki de─či┼čkeni, fonksiyonun d─▒┼č─▒ndaki ayr─▒, de─či┼čmeyen bir de─čere ba─člamakt─▒r:

 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++) {
  // and now let's run each one to see
  funcs[j]();
} 

JavaScript'te blok kapsam─▒ olmad─▒─č─▒ i├žin - sadece fonksiyon kapsam─▒ - fonksiyon olu┼čturma i┼člevini yeni bir fonksiyona sararak, "i" de─čerinin istedi─činiz gibi kalmas─▒n─▒ sa─člars─▒n─▒z.


2015 ├ç├Âz├╝m├╝: Her Biri i├žin

Array.prototype.forEach ─░┼člevin g├Âreceli olarak yayg─▒n olmas─▒yla (2015'te), ├Âncelikle bir dizi de─čer ├╝zerinden yinelemenin s├Âz konusu oldu─ču durumlarda, .forEach() her yinelemede farkl─▒ bir kapatma elde etmek i├žin temiz ve do─čal bir yol sa─člad─▒─č─▒n─▒ belirtmek gerekir. Yani, de─čerler i├žeren bir dizi diziniz oldu─čunu varsayal─▒m (DOM referanslar─▒, nesneler, ne olursa olsun) ve her bir ├Â─čeye ├Âzel geri aramalar ayarlama sorunu ortaya ├ž─▒karsa, bunu yapabilirsiniz:

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

Fikir, .forEach d├Âng├╝ ile birlikte kullan─▒lan geri ├ža─č─▒rma i┼člevinin her ├ža─čr─▒lmas─▒n─▒n kendi kapanmas─▒ olaca─č─▒d─▒r. Bu i┼čleyiciye iletilen parametre, yinelemenin belirli ad─▒m─▒na ├Âzg├╝ dizi ├Â─česidir. E┼čzamans─▒z bir geri aramada kullan─▒l─▒yorsa, yinelemenin di─čer ad─▒mlar─▒nda olu┼čturulan di─čer geri aramalar─▒n hi├žbiriyle ├žarp─▒┼čmaz.

E─čer jQuery'de ├žal─▒┼č─▒yorsan─▒z, $.each() fonksiyon size benzer bir yetenek kazand─▒r─▒r.


ES6 ├ž├Âz├╝m├╝: let

ECMAScript 6 (ES6) , temelli de─či┼čkenlerden farkl─▒ olarak ele al─▒nan yeni let ve const anahtar kelimeler sunar var . ├ľrne─čin, let tabanl─▒ bir dizine sahip bir d├Âng├╝de, d├Âng├╝deki her yineleme, i her de─čerin d├Âng├╝ i├žinde kapsam─▒ i├žin yeni bir de─čere sahip olacakt─▒r , bu nedenle kodunuz bekledi─činiz gibi ├žal─▒┼č─▒r. ├çok fazla kaynak var, ancak 2ality'nin blok kapsam─▒ndaki g├Ârevini m├╝kemmel bir bilgi kayna─č─▒ olarak ├Âneriyorum .

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

Bununla birlikte, Edge 14'ten ├Ânceki IE9-IE11 ve Edge'in destekledi─čini, let ancak yukar─▒dakilerin yanl─▒┼č oldu─čunu s├Âyledi─čine dikkat edin ( i her seferinde yeni bir ┼čey yaratmazlar , bu y├╝zden yukar─▒daki t├╝m i┼člevler bizim kulland─▒─č─▒m─▒z gibi g├╝nl├╝k kayd─▒ yapar var ). Kenar 14 nihayet do─čru al─▒r.


2058







Deneyin:

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

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

D├╝zenleme (2014):

┼×ahsen bence @ AustÔÇÖ─▒n kullan─▒m─▒ hakk─▒ndaki en son cevab─▒ .bind ┼čimdi bu t├╝r ┼čeyleri yapman─▒n en iyi yoludur. Lo-├žizgi ├žizgi var / da var _.partial ihtiyac─▒n─▒z veya u─čra┼čmak istemedi─činizde bind 's thisArg .


369







Hen├╝z bahsedilmemi┼č bir ba┼čka yol da Function.prototype.bind

 var funcs = {};
for (var i = 0; i < 3; i++) {
  funcs[i] = function(x) {
    console.log('My value: ' + x);
  }.bind(this, i);
}
for (var j = 0; j < 3; j++) {
  funcs[j]();
} 

G├ťNCELLE┼×T─░RME

@Squint ve @mekdev taraf─▒ndan belirtildi─či gibi, ├Ânce ilmekin d─▒┼č─▒nda bir i┼člev olu┼čturarak ve ard─▒ndan ilmek i├žindeki sonu├žlar─▒ ba─člayarak daha iyi performans elde edersiniz.

 function log(x) {
  console.log('My value: ' + x);
}

var funcs = [];

for (var i = 0; i < 3; i++) {
  funcs[i] = log.bind(this, i);
}

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


335


2013-10-11





Hemen ├ça─čr─▒lan ─░┼člev ─░fadesi kullanarak , bir dizin de─či┼čkenini i├žine alman─▒n en basit ve en okunakl─▒ yolu:

 for (var i = 0; i < 3; i++) {

    (function(index) {

        console.log('iterator: ' + index);
        //now you can also loop an ajax call here 
        //without losing track of the iterator value:   $.ajax({});
    
    })(i);

} 

Bu, yineleyiciyi i bizim tan─▒mlad─▒─č─▒m─▒z isimsiz fonksiyona g├Ânderir index . Bu, de─či┼čkenin i IIFE i├žindeki herhangi bir asenkron i┼člevsellikte daha sonra kullan─▒lmak ├╝zere sakland─▒─č─▒ bir kapatma olu┼čturur .


261







Partiye biraz ge├ž kald─▒m, ancak bug├╝n bu konuyu ara┼čt─▒r─▒yordum ve cevaplar─▒n ├žo─čunun Javascript'in kapsamlar─▒ nas─▒l ele ald─▒─č─▒n─▒ tam olarak ├ž├Âzemedi─čini fark ettim.

Di─čerlerinin de belirtti─či gibi, problem i├ž fonksiyonun ayn─▒ i de─či┼čkeni referans g├Âstermesidir. ├ľyleyse neden her yinelemede yeni bir yerel de─či┼čken yaratm─▒yoruz, bunun yerine i├žsel i┼člevsellik ba┼čvurusu yapal─▒m?

 //overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
    var ilocal = i; //create a new local variable
    funcs[i] = function() {
        console.log("My value: " + ilocal); //each should reference its own local variable
    };
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
} 

T─▒pk─▒ daha ├Ânce oldu─ču gibi, her bir i├ž fonksiyonun atanm─▒┼č olan son de─čeri verdi─či yerde i , ┼čimdi her i├ž fonksiyon sadece atanm─▒┼č olan son de─čeri verir ilocal . Fakat her yinelemenin kendine ait olmas─▒ gerekmez ilocal mi?

Anla┼č─▒lan sorun bu. Her yineleme ayn─▒ kapsam─▒ payla┼č─▒yor, bu y├╝zden birinciden sonraki her yineleme sadece ├╝zerine yaz─▒yor ilocal . G├Ânderen MDN'yi :

├ľnemli: JavaScript'in blok kapsam─▒ yok. Bir blo─čun getirdi─či de─či┼čkenler, i├žerme i┼člevine veya komut dosyas─▒na dahil edilir ve bunlar─▒ ayarlaman─▒n etkileri blo─čun ├Âtesinde kal─▒r. Ba┼čka bir deyi┼čle, blok ifadeleri kapsam i├žermez. "Ba─č─▒ms─▒z" bloklar ge├žerli bir s├Âzdizimi olmas─▒na ra─čmen, JavaScript'te ba─č─▒ms─▒z bloklar kullanmak istemezsiniz, ├ž├╝nk├╝ C veya Java'daki bu t├╝r bloklar gibi bir ┼čey yapt─▒klar─▒n─▒ d├╝┼č├╝n├╝yorsan─▒z, yapt─▒klar─▒n─▒ yapmazlar.

Vurgu i├žin yinelendi:

JavaScript'in blok kapsam─▒ yok. Bir blo─čun getirdi─či de─či┼čkenler, i├žerme i┼člevine veya komut dosyas─▒na dahil edilir

Bunu ilocal her yinelemede bildirmeden ├Ânce kontrol ederek g├Ârebiliriz :

 //overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
  console.log(ilocal);
  var ilocal = i;
} 

Bu tam olarak bu hatan─▒n ├žok zor olmas─▒n─▒n nedeni budur. Bir de─či┼čkeni yeniden bildirseniz bile, Javascript bir hata atmaz ve JSLint bir uyar─▒ bile atmaz. Bu ayn─▒ zamanda, bunu ├ž├Âzmenin en iyi yolunun, Javascript'te i├ž fonksiyonlar─▒n d─▒┼č de─či┼čkenlere eri┼čimi oldu─ču fikri olan kapamalardan yararlanmakt─▒r, ├ž├╝nk├╝ i├ž kapsamlar, d─▒┼č kapsamlar─▒ "kaplar".


Kapaklar

Bu ayn─▒ zamanda, i├ž i┼člevlerin d─▒┼č de─či┼čkenleri "tuttu─ču" ve d─▒┼č i┼člev d├Ând├╝─č├╝ halde onlar─▒ canl─▒ tuttu─ču anlam─▒na gelir. Bunu kullanmak i├žin, yaln─▒zca yeni bir kapsam olu┼čturmak, yeni kapsamda bildirmek ilocal ve kullan─▒lan bir i├ž i┼člev d├Ând├╝rmek i├žin yaln─▒zca bir sarmalay─▒c─▒ i┼člevi olu┼čturur ve ├ža─č─▒r─▒r─▒z ilocal (a┼ča─č─▒da daha fazla a├ž─▒klama):

 //overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
    funcs[i] = (function() { //create a new scope using a wrapper function
        var ilocal = i; //capture i into a local var
        return function() { //return the inner function
            console.log("My value: " + ilocal);
        };
    })(); //remember to run the wrapper function
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
} 

Bir sarmalay─▒c─▒ fonksiyonun i├žinde i├ž fonksiyonun yarat─▒lmas─▒, i├ž fonksiyona yaln─▒zca eri┼čebilece─či ├Âzel bir ortam, bir "kapatma" verir. B├Âylece, sarmalay─▒c─▒ i┼člevini her ├ža─č─▒rd─▒─č─▒m─▒zda, ilocal de─či┼čkenlerin birbiriyle ├žarp─▒┼čmamas─▒n─▒ ve ├╝zerine yazmamas─▒n─▒ sa─člamak i├žin kendi ayr─▒ ortam─▒yla yeni bir i├ž i┼člev yarat─▒r─▒z . Birka├ž k├╝├ž├╝k optimizasyon, di─čer bir├žok SO kullan─▒c─▒s─▒n─▒n verdi─či son cevab─▒ verir:

 //overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
    funcs[i] = wrapper(i);
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}
//creates a separate environment for the inner function
function wrapper(ilocal) {
    return function() { //return the inner function
        console.log("My value: " + ilocal);
    };
} 

G├╝ncelle┼čtirme

Art─▒k ana ak─▒m ES6 ile, let blok kapsam─▒ndaki de─či┼čkenler olu┼čturmak i├žin yeni anahtar kelimeyi ┼čimdi kullanabiliriz :

 //overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (let i = 0; i < 3; i++) { // use "let" to declare "i"
    funcs[i] = function() {
        console.log("My value: " + i); //each should reference its own local variable
    };
}
for (var j = 0; j < 3; j++) { // we can use "var" here without issue
    funcs[j]();
} 

┼×imdi ne kadar kolay oldu─čuna bak! Daha fazla bilgi i├žin bilgimin dayand─▒─č─▒ bu cevaba bak─▒n─▒z .


154







Yayg─▒n olarak desteklenen ES6 ile bu sorunun en iyi cevab─▒ de─či┼čti. ES6 bu ko┼čul i├žin let ve const anahtar kelimelerini sa─člar . Kapaklarla u─čra┼čmak yerine sadece ┼č├Âyle let bir d├Âng├╝ kapsam─▒ de─či┼čkeni ayarlamak i├žin kullanabiliriz :

 var funcs = [];

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

val daha sonra d├Âng├╝n├╝n belirli bir d├Ân├╝┼č├╝ne ├Âzg├╝ olan bir nesneye i┼čaret edecek ve ek kapatma g├Âsterimi olmadan do─čru de─čeri d├Ând├╝recektir. Bu a├ž─▒k├ža bu problemi basitle┼čtiriyor.

const let ─░lk atamadan sonra de─či┼čken isminin yeni bir referansa geri d├Ând├╝r├╝lemeyece─či ek k─▒s─▒tlamaya benzer .

Taray─▒c─▒ deste─či, taray─▒c─▒lar─▒n son s├╝r├╝mlerini hedefleyenler i├žin ┼čimdi burada. const / let ┼ču anda en son Firefox, Safari, Edge ve Chrome'da desteklenmektedir. Ayr─▒ca D├╝─č├╝mde desteklenir ve Babel gibi derleme ara├žlar─▒ndan yararlanarak her yerde kullanabilirsiniz. Burada ├žal─▒┼čan bir ├Ârnek g├Ârebilirsiniz: http://jsfiddle.net/ben336/rbU4t/2/

Buradaki dok├╝manlar:

Bununla birlikte, Edge 14'ten ├Ânceki IE9-IE11 ve Edge'in destekledi─čini, let ancak yukar─▒dakilerin yanl─▒┼č oldu─čunu s├Âyledi─čine dikkat edin ( i her seferinde yeni bir ┼čey yaratmazlar , bu y├╝zden yukar─▒daki t├╝m i┼člevler bizim kulland─▒─č─▒m─▒z gibi g├╝nl├╝k kayd─▒ yapar var ). Kenar 14 nihayet do─čru al─▒r.


145







Bunu s├Âylemenin bir ba┼čka yolu i , i┼člevinizde i┼člev olu┼čturma zaman─▒ de─čil, i┼člev y├╝r├╝tme s─▒ras─▒nda ba─čl─▒ olmas─▒d─▒r.

Kapatma i olu┼čturdu─čunuzda, kapama olu┼čturdu─čunuzdaki gibi bir kopyas─▒na de─čil, d─▒┼č kapsamda tan─▒mlanan de─či┼čkene bir referanst─▒r. Y├╝r├╝tme s─▒ras─▒nda de─čerlendirilecektir.

Di─čer cevaplar─▒n ├žo─ču, sizin i├žin de─čeri de─či┼čtirmeyecek ba┼čka bir de─či┼čken olu┼čturarak ├žal─▒┼čman─▒n yollar─▒n─▒ sunar.

Sadece netlik i├žin bir a├ž─▒klama ekleyece─čimi d├╝┼č├╝nd├╝m. Bir ├ž├Âz├╝m i├žin, ┼čahsen, Harto ile giderdim, ├ž├╝nk├╝ buradaki cevaplardan en a├ž─▒klay─▒c─▒ yoldur. G├Ânderilen kodlardan herhangi biri i┼če yarayacak, ancak neden yeni bir de─či┼čken (Freddy ve 1800'ler) tan─▒mlad─▒─č─▒m─▒ veya garip g├Âm├╝l├╝ kapama s├Âzdizimini (apphacker) a├ž─▒klad─▒─č─▒m─▒ a├ž─▒klamak i├žin bir kapatma fabrikas─▒ se├žece─čim.


85







Anlaman─▒z gereken ┼čey, javascript'teki de─či┼čkenlerin kapsam─▒ fonksiyona dayan─▒r. Bu, blok kapsam─▒na sahip oldu─čunuz c # ifadesinden ├Ânemli bir farkt─▒r ve de─či┼čkeni for i├žindeki bir taneye kopyalamak i┼če yarayacakt─▒r.

De─či┼čken ┼čimdi i┼člev kapsam─▒na sahip oldu─čundan, i┼čleyicinin cevab─▒ gibi fonksiyonun geri d├Ând├╝r├╝lmesini de─čerlendiren bir fonksiyona sar─▒lmas─▒ hile yapar.

Ayr─▒ca blok kapsam─▒ kural─▒n─▒n kullan─▒lmas─▒na izin verecek var yerine let kelimesi de var. Bu durumda for i├žindeki bir de─či┼čkeni tan─▒mlamak hile yapar. Bununla birlikte, let anahtar s├Âzc├╝─č├╝ uyumluluk nedeniyle pratik bir ├ž├Âz├╝m de─čildir.

 var funcs = {};

for (var i = 0; i < 3; i++) {
  let index = i; //add this
  funcs[i] = function() {
    console.log("My value: " + index); //change to the copy
  };
}

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


70







Teknikte, Bjorn's (apphacker) 'a benzeyen, de─či┼čkende de─čeri parametre olarak ge├žirmekten ziyade, bazen daha a├ž─▒k bir ┼čekilde belirtmenize izin veren ba┼čka bir varyasyon:

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

Hangi tekni─či kullan─▒rsan─▒z kullan─▒n, index de─či┼čken i├ž fonksiyonun d├Ând├╝r├╝len kopyas─▒na ba─čl─▒ bir ├že┼čit statik de─či┼čken haline gelir. Yani, ├ža─čr─▒lar─▒ aras─▒nda de─čerindeki de─či┼čiklikler korunur. ├çok kullan─▒┼čl─▒ olabilir.


58







Bu, JavaScript'teki kapan─▒┼člar─▒ kullanmadaki yayg─▒n hatay─▒ a├ž─▒klar.

Bir fonksiyon yeni bir ortam tan─▒mlar

D├╝┼č├╝nmek:

 function makeCounter()
{
  var obj = {counter: 0};
  return {
    inc: function(){obj.counter ++;},
    get: function(){return obj.counter;}
  };
}

counter1 = makeCounter();
counter2 = makeCounter();

counter1.inc();

alert(counter1.get()); // returns 1
alert(counter2.get()); // returns 0
 

Her zaman makeCounter ├ža─čr─▒l─▒rsa, {counter: 0} yeni bir nesnenin olu┼čturulmas─▒na neden olur. Ayr─▒ca, obj yeni nesneye at─▒fta bulunmak i├žin yeni bir kopyas─▒ olu┼čturulur. B├Âylece counter1 ve counter2 birbirinden ba─č─▒ms─▒zd─▒r.

D├Âng├╝lerdeki kapaklar

D├Âng├╝de bir kapatma kullanmak zordur.

D├╝┼č├╝nmek:

 var counters = [];

function makeCounters(num)
{
  for (var i = 0; i < num; i++)
  {
    var obj = {counter: 0};
    counters[i] = {
      inc: function(){obj.counter++;},
      get: function(){return obj.counter;}
    }; 
  }
}

makeCounters(2);

counters[0].inc();

alert(counters[0].get()); // returns 1
alert(counters[1].get()); // returns 1
 

Bildirim o counters[0] ve counters[1] vard─▒r de─čil ba─č─▒ms─▒z. Asl─▒nda, ayn─▒ ┼čekilde ├žal─▒┼č─▒yorlar obj !

Bunun nedeni obj , d├Âng├╝n├╝n t├╝m yinelemelerinde , yaln─▒zca performans nedenleriyle payla┼č─▒lan yaln─▒zca bir kopyan─▒n olmas─▒d─▒r . {counter: 0} Her yinelemede yeni bir nesne olu┼čtursa da , ayn─▒ kopyas─▒ obj en yeni nesneye referansla g├╝ncellenir.

├ç├Âz├╝m, ba┼čka bir yard─▒mc─▒ i┼člev kullanmakt─▒r:

 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);
  }
}
 

Bu ├žal─▒┼č─▒r ├ž├╝nk├╝ do─črudan fonksiyon kapsam─▒ndaki yerel de─či┼čkenlerin yan─▒ s─▒ra fonksiyon arg├╝man de─či┼čkenlerinin giri┼čine yeni kopyalar tahsis edilir.

Detayl─▒ bir tart─▒┼čma i├žin l├╝tfen JavaScript kapatma tuzaklar─▒na ve kullan─▒mlar─▒na bak─▒n─▒z.


52


2013-04-20





En basit ├ž├Âz├╝m,

Kullanmak yerine:

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

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

hangi 3 kez "2" uyar─▒yor. Bunun nedeni, d├Âng├╝ i├žin olu┼čturulan anonim i┼člevlerin ayn─▒ kapan─▒┼č─▒ payla┼čmas─▒ ve bu kapan─▒┼čta da de─čerinin i ayn─▒ olmas─▒d─▒r. Payla┼č─▒lan kapanmay─▒ ├Ânlemek i├žin bunu kullan─▒n:

 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]();
}
 

Bunun arkas─▒ndaki fikir, for d├Âng├╝s├╝n├╝n t├╝m g├Âvdesini bir IIFE (Hemen ├ça─čr─▒lan ─░┼člev ─░fadesi) ile kaplamak ve new_i bir parametre olarak ge├žmek ve onu yakalamakt─▒r i . Anonim i┼člev hemen ├žal─▒┼čt─▒r─▒ld─▒─č─▒ndan, i de─čer, anonim i┼člev i├žinde tan─▒mlanan her i┼člev i├žin farkl─▒d─▒r.

Bu ├ž├Âz├╝m, bu sorunla kar┼č─▒la┼čan orijinal kodda minimum de─či┼čiklik yap─▒lmas─▒ gerekece─činden, bu t├╝r herhangi bir soruna uyacak gibi g├Âr├╝n├╝yor. Asl─▒nda, bu tasar─▒m gere─či, hi├ž bir sorun olmamal─▒!


48







bu k─▒sa olan─▒ dene

  • dizi yok

  • d├Âng├╝ i├žin fazladan yok


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

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

http://jsfiddle.net/7P6EN/


30







─░┼čte kullanan basit bir ├ž├Âz├╝m forEach (IE9'a geri d├Ân├╝yor):

 var funcs = [];
[0,1,2].forEach(function(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
} 

Bask─▒lar:

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

28







OP taraf─▒ndan g├Âsterilen kodla ilgili ana sorun i , ikinci d├Âng├╝ye kadar asla okunmamas─▒d─▒r. G├Âstermek i├žin, kodun i├žinde bir hata g├Ârd├╝─č├╝n├╝z├╝ hayal edin

 funcs[i] = function() {            // and store them in funcs
    throw new Error("test");
    console.log("My value: " + i); // each should log its value.
};
 

Hata funcs[someIndex] , y├╝r├╝t├╝lene kadar olu┼čmaz () . Bu ayn─▒ mant─▒─č─▒ kullanarak, de─čerinin i de bu noktaya kadar toplanmad─▒─č─▒ a├ž─▒k olmal─▒d─▒r . Orijinal d├Âng├╝ bitti─činde, durumun ba┼čar─▒s─▒z olmas─▒na ve d├Âng├╝n├╝n sona ermesine neden olan de─čeri i++ getirir . Bu noktada, bir zaman ve bu y├╝zden kullan─▒l─▒r ve de─čerlendirilir, bu 3 - her zaman. i 3 i < 3 i 3 funcs[someIndex]() i

Bunu a┼čmak i i├žin, kar┼č─▒la┼č─▒ld─▒─č─▒ gibi de─čerlendirme yapman─▒z gerekir . Bunun zaten funcs[i] (3 benzersiz indeksin oldu─ču) ┼čeklinde oldu─čunu not edin. Bu de─čeri yakalaman─▒n birka├ž yolu vard─▒r. Bunlardan biri, burada zaten g├Âsterilen birka├ž ┼čekilde g├Âsterilen bir i┼čleve parametre olarak ge├žirmektir.

Di─čer bir se├ženek ise de─či┼čken ├╝zerinde kapanabilecek bir fonksiyon nesnesi olu┼čturmakt─▒r. Bu ┼čekilde ba┼čar─▒labilir

jsFiddle Demo

 funcs[i] = new function() {   
    var closedVariable = i;
    return function(){
        console.log("My value: " + closedVariable); 
    };
};
 

26







JavaScript i┼člevleri, bildirildikten sonra eri┼čebilecekleri kapsam─▒ "kapat─▒r" ve bu kapsam de─či┼čti─činde de─či┼čkenler olsa bile bu kapsama eri┼čimi korur.

 var funcs = []

for (var i = 0; i < 3; i += 1) {
  funcs[i] = function () {
    console.log(i)
  }
}

for (var k = 0; k < 3; k += 1) {
  funcs[k]()
} 

Yukar─▒daki dizideki her i┼člev, global kapsam─▒n ├╝zerine kapan─▒r (global, bunun nedeni, bildirildikleri kapsam olmas─▒ nedeniyle).

Daha sonra bu fonksiyonlar i global kapsamdaki en g├╝ncel de─čeri kaydederek ├ža─čr─▒l─▒r . Kapanman─▒n b├╝y├╝s├╝ ve hayal k─▒r─▒kl─▒─č─▒ budur.

"JavaScript ─░┼člevleri, bildirildikleri kapsam─▒n ├╝zerine yakla┼č─▒yor ve bu kapsam─▒n i├žindeki de─či┼čken de─čerler olsa bile bu kapsama eri┼čimi koruyor."

Bunu kullanmak let yerine var , for d├Âng├╝ her ├žal─▒┼čt─▒─č─▒nda yeni bir kapsam olu┼čturarak, kapanacak her fonksiyon i├žin ayr─▒ bir kapsam olu┼čturarak bunu ├ž├Âzer . ├çe┼čitli ba┼čka teknikler de ayn─▒ ┼čeyi ekstra fonksiyonlarla yapar.

 var funcs = []

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

for (var k = 0; k < 3; k += 1) {
  funcs[k]()
} 

( let de─či┼čkenleri blok kapsam─▒ haline getirir. Bloklar k├╝me parantezleri ile g├Âsterilir, ancak for d├Âng├╝s├╝ i├žin ba┼člang─▒├ž ÔÇőÔÇőde─či┼čkeninin i bizim durumumuzda parantez i├žinde bildirildi─či kabul edilir.)


22







├çe┼čitli ├ž├Âz├╝mler okuduktan sonra, bu ├ž├Âz├╝mlerin ├žal─▒┼čmas─▒n─▒n nedeninin kapsam zinciri kavram─▒na ba─čl─▒ oldu─čunu eklemek isterim . JavaScript, y├╝r├╝tme s─▒ras─▒nda bir de─či┼čkeni ├ž├Âzme y├Ântemidir.

  • Her i┼člev tan─▒m─▒, taraf─▒ndan bildirilen t├╝m yerel de─či┼čkenlerden var ve bununla ilgili olarak bir kapsam olu┼čturur arguments .
  • Ba┼čka bir (d─▒┼č) i┼člevin i├žinde tan─▒mlanm─▒┼č i├žsel bir i┼čleve sahipsek, bu bir zincir olu┼čturur ve y├╝r├╝tme s─▒ras─▒nda kullan─▒lacakt─▒r.
  • Bir i┼člev y├╝r├╝t├╝ld├╝─č├╝nde, ├žal─▒┼čma zaman─▒, kapsam zincirini arayarak de─či┼čkenleri de─čerlendirir . E─čer bir de─či┼čken zincirin belirli bir noktas─▒nda bulunursa, onu aramay─▒ durduracak ve kullanmay─▒ b─▒rakacakt─▒r, aksi takdirde ait oldu─ču global kapsama ula┼čana kadar devam eder window .

─░lk kodda:

 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
 

Ne zaman funcs i┼čletilirse, kapsam zinciri olacak function inner -> global . De─či┼čken i bulunamad─▒─č─▒ndan function inner (ne kullan─▒ld─▒─č─▒n─▒ ve var ne de arg├╝man olarak iletildi─čini) i bulunmad─▒─č─▒ndan, sonu├žta global kapsamda de─čeri bulunana kadar aramaya devam eder window.i .

Bunu bir d─▒┼č fonksiyona sararak ya harto did gibi bir yard─▒mc─▒ i┼člevi a├ž─▒k├ža tan─▒mlay─▒n ya da Bjorn did gibi bir anonim i┼člev kullan─▒n :

 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
 

Ne zaman funcs i┼čletilirse, ┼čimdi kapsam zinciri olacak function inner -> function outer . Bu s├╝re i , d─▒┼č fonksiyonun for d├Âng├╝s├╝nde 3 kez y├╝r├╝t├╝len kapsamda bulunabilir, her seferinde i do─čru ┼čekilde ba─članm─▒┼č de─čer vard─▒r . window.i ─░├ž y├╝r├╝t├╝ld├╝─č├╝ zaman de─čerini kullanmaz .

Daha fazla ayr─▒nt─▒ burada bulunabilir
D├Âng├╝de kapama yaratma konusundaki yayg─▒n hatay─▒ burada sahip oldu─čumuz gibi, ayr─▒ca kapatmaya ve performans de─čerlendirmesine neden ihtiya├ž duydu─čumuzu i├žerir.


13







ES6 blok seviyeli kapsam─▒n yeni ├Âzellikleri ile y├Ânetilir:

 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
}
 

OP'nin sorusundaki kod let yerine var .


13







Hi├ž kimse hen├╝z forEach yerel de─či┼čkenleri kullanmaktan (yeniden) ka├ž─▒nmak i├žin bu i┼člevi kullanmay─▒ ├Ânermedi. Asl─▒nda, for(var i ...) art─▒k bu sebeple kullanm─▒yorum .

 [0,2,3].forEach(function(i){ console.log('My value:', i); });
// My value: 0
// My value: 2
// My value: 3
 

// forEach harita yerine kullanmak i├žin d├╝zenlendi .


10







Bu soru ger├žekten JavaScript'in tarihini g├Âsteriyor! Art─▒k ok i┼člevleriyle blok kapsamay─▒ engelleyebilir ve Object y├Ântemlerini kullanarak d├Âng├╝leri do─črudan DOM d├╝─č├╝mlerinden i┼čleyebiliriz.

 const funcs = [1, 2, 3].map(i => () => console.log(i));
funcs.map(fn => fn()) 

 const buttons = document.getElementsByTagName("button");
Object
  .keys(buttons)
  .map(i => buttons[i].addEventListener('click', () => console.log(i))); 
 <button>0</button><br>
<button>1</button><br>
<button>2</button> 


9







Orijinal ├Ârne─činizin ├žal─▒┼čmamas─▒n─▒n nedeni, d├Âng├╝de yaratt─▒─č─▒n─▒z t├╝m kapaklar─▒n ayn─▒ ├žer├ževeye referans vermesidir. Asl─▒nda, tek bir i de─či┼čkenle bir nesnede 3 y├Ântem olmas─▒ . Hepsi ayn─▒ de─čeri bast─▒rd─▒.


8







Her ┼čeyden ├Ânce, bu kodda neyin yanl─▒┼č oldu─čunu anlay─▒n:

 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
}
 

Burada funcs[] dizi ba┼člat─▒l─▒rken, i art─▒r─▒l─▒r, funcs dizi ba┼člat─▒l─▒r ve func dizinin boyutu 3 olur i = 3, . ┼×imdi funcs[j]() ├ža─čr─▒ld─▒─č─▒nda, yine i de 3'e y├╝kseltilmi┼č olan de─či┼čkeni kullan─▒yor .

┼×imdi bunu ├ž├Âzmek i├žin bir├žok se├žene─čimiz var. A┼ča─č─▒da bunlardan ikisi:

  1. Biz ba┼člatabilir i ile let veya yeni bir de─či┼čkeni ba┼člatmak index ile let ve kar┼č─▒ e┼čit hale i . B├Âylece ├ža─čr─▒ yap─▒l─▒rken index kullan─▒lacak ve kapsam─▒ ba┼člat─▒ld─▒ktan sonra sona erecek. Ve ├ža─čr─▒ i├žin index tekrar ba┼člat─▒lacak:

     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]();                        
    }
     
  2. Di─čer Se├ženek tempFunc , as─▒l i┼člevi d├Ând├╝ren birini tan─▒tmak olabilir :

     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]();                        
    }
     

8







Kapama yap─▒s─▒n─▒ kullan─▒n , bu d├Âng├╝ i├žin fazladan azalt─▒r. D├Âng├╝ i├žin bir tek yapabilirsiniz.

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

7







Size bildirmek ger├žekte neler oldu─čunu, kontrol edecek var ve let teker teker.

Case1 : kullanma var

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

┼×imdi krom konsol pencerenizi F12 tu┼čuna basarak a├ž─▒n ve sayfay─▒ yenileyin. Dizinin i├žindeki her 3 i┼člevi de geni┼čletin. .Exp ad─▒nda bir ├Âzellik g├Âr├╝rs├╝n├╝z [[Scopes]] . Bir tane dizi nesnesi g├Âreceksiniz "Global" , onu geni┼čletin. 'i' Nesneye, de─čeri 3 olan bir ├Âzellik bulacaks─▒n─▒z .


g├Âr├╝nt├╝ tan─▒m─▒n─▒ buraya girin


g├Âr├╝nt├╝ tan─▒m─▒n─▒ buraya girin

Sonu├ž:

  1. Bir 'var' fonksiyonun d─▒┼č─▒n─▒ kullanarak bir de─či┼čken bildirdi─činizde , global de─či┼čken haline gelir (yazarak i ya window.i da konsol penceresinden kontrol edebilirsiniz.
  2. Bildirdi─činiz annominous fonksiyonu, siz ├ža─čr─▒lmazsa, fonksiyon i├žindeki de─čeri ├ža─č─▒rmaz ve kontrol etmez.
  3. ─░┼člevi ├ža─č─▒rd─▒─č─▒n─▒zda, console.log("My value: " + i) de─čeri Global nesnesinden al─▒r ve sonucu g├Âr├╝nt├╝ler.

CASE2: let kullanarak

┼×imdi de─či┼čtirmek 'var' ile 'let'

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

Ayn─▒ ┼čeyi yap─▒n, kapsamlara gidin. ┼×imdi iki nesne g├Âreceksiniz "Block" ve "Global" . ┼×imdi Block nesneyi geni┼čletin , orada 'i' nin tan─▒mland─▒─č─▒n─▒ g├Âreceksiniz ve garip olan, her fonksiyon i├žin e─čer i farkl─▒ ise (0, 1, 2).


g├Âr├╝nt├╝ tan─▒m─▒n─▒ buraya girin

Sonu├ž:

'let' ─░┼člevin d─▒┼č─▒nda bile olsa, ancak d├Âng├╝ i├žinde de─či┼čken kulland─▒─č─▒n─▒zda , bu de─či┼čken bir Global de─či┼čken olmayacak Block , yaln─▒zca ayn─▒ i┼člev i├žin kullan─▒labilen bir seviye de─či┼čkeni olacak . Bu nedenle, i farkl─▒ bir de─čer elde ediyoruz. Her fonksiyon i├žin fonksiyonlar─▒ ├ža─č─▒rd─▒─č─▒m─▒zda.

Nas─▒l daha yak─▒n i┼če yarad─▒─č─▒ hakk─▒nda daha fazla ayr─▒nt─▒ i├žin, l├╝tfen harika video e─čitimini okuyun https://youtu.be/71AtaJpJHw0


7







forEach Bir s├Âzde menzil olu┼čturma ile kendi kapan─▒┼č─▒ olan i┼člevi kullanmay─▒ tercih ederim :

 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
}
 

Bu, di─čer dillerdeki aral─▒klardan daha ├žirkin g├Âr├╝n├╝yor, ancak IMHO di─čer ├ž├Âz├╝mlerden daha az canavar.


4







Ve yine ba┼čka bir ├ž├Âz├╝m: ba┼čka bir d├Âng├╝ olu┼čturmak yerine this , return i┼člevine ba─člaman─▒z yeterli .

 var funcs = [];

function createFunc(i) {
  return function() {
    console.log('My value: ' + i); //log value of i.
  }.call(this);
}

for (var i = 1; i <= 5; i++) {  //5 functions
  funcs[i] = createFunc(i);     // call createFunc() i=5 times
} 

Ba─članarak bu , sorunu ├ž├Âzer de.


4







Query-js (*) gibi veri listeleri i├žin bildirim mod├╝l├╝ kullanabilirsiniz . Bu durumlarda ┼čahsen, daha az ┼ča┼č─▒rt─▒c─▒ olmayan, bildirimsel bir yakla┼č─▒m buluyorum

 var funcs = Query.range(0,3).each(function(i){
     return  function() {
        console.log("My value: " + i);
    };
});
 

Sonra ikinci d├Âng├╝n├╝z├╝ kullanabilir ve beklenen sonucu elde edebilirsiniz ya da

 funcs.iterate(function(f){ f(); });
 

(*) Ben sorgu-js 'in yazar─▒y─▒m ve bunun i├žin kullanmaya ├Ânyarg─▒l─▒y─▒m, bu y├╝zden s├Âzlerimi yaln─▒zca bildirici yakla┼č─▒m i├žin s├Âz konusu k├╝t├╝phane i├žin ├Âneri olarak alma :)


3







Pek ├žok ├ž├Âz├╝m do─čru g├Âz├╝k├╝yor, ancak bunlar Currying gibi durumlar i├žin i┼člevsel bir programlama tasar─▒m deseni olarak adland─▒r─▒ld─▒─č─▒ndan bahsetmiyorlar . Taray─▒c─▒ya ba─čl─▒ olarak ciltlemeden 3-10 kat daha h─▒zl─▒.

 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);
  }
}
 

Farkl─▒ taray─▒c─▒lardaki performans art─▒┼č─▒n─▒ g├Âr├╝n .


3







Kodunuz ├žal─▒┼čm─▒yor, ├ž├╝nk├╝:

 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?
 

┼×imdi soru, i fonksiyon ├ža─čr─▒ld─▒─č─▒nda de─či┼čkenin de─čeri nedir? ─░lk d├Âng├╝ ko┼čulu ile olu┼čturuldu─čundan i < 3 , ko┼čul yanl─▒┼č oldu─čunda derhal durur, yani ├Âyle i = 3 .

─░┼člevlerinizin yarat─▒ld─▒─č─▒ zaman kodlar─▒n─▒n hi├žbirinin ├žal─▒┼čt─▒r─▒lmad─▒─č─▒n─▒, yaln─▒zca daha sonraya kaydedilece─čini anlamal─▒s─▒n─▒z. Ve daha sonra ├ža─čr─▒ld─▒klar─▒nda, terc├╝man onlar─▒ y├╝r├╝t├╝r ve ÔÇť┼×u anki de─čeri nedir i ?ÔÇŁ Diye sorar.

Bu nedenle, amac─▒n─▒z ├Ânce i i┼člevinin de─čerini, ard─▒ndan i┼člevden sonra kaydetmeyi hedeflemektir funcs . Bu, ├Ârne─čin ┼ču ┼čekilde yap─▒labilir:

 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
}
 

Bu ┼čekilde, her i┼člevin kendi de─či┼čkeni olacak x ve bunu her yinelemenin x de─čerine ayarlad─▒k i .

Bu, bu sorunu ├ž├Âzmenin bir├žok yolundan sadece biri.


3







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

3







Var yerine let (blocked-kapsam) kullan─▒n.

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


3