kzen.dev
  • Vprašanja
  • Oznake
  • Uporabniki
Obvestila
Nagrade
Registracija
Once you register, you will be notified of replies and comments to your questions.
Prijavite se
Če že imate račun, se prijavite in preverite nova obvestila.
Za dodana vprašanja, odgovore in komentarje boste prejeli nagrade.
Več
Vir:
Uredi
 nickf
nickf
Question

Zapiranje v jeziku JavaScript znotraj zank - preprost praktični primer

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

Izpisuje tole:

Moja vrednost: 3 Moja vrednost: 3 Moja vrednost: 3

Medtem ko bi želel, da se izpiše: Moja vrednost: 0 Moja vrednost: 1 Moja vrednost: 2


Enaka težava se pojavi, kadar je zamuda pri izvajanju funkcije posledica uporabe poslušalcev dogodkov:

-- begin snippet: js hide: false console: true babel: false -->

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>

... ali asinhrone kode, npr. z uporabo obljub:

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

Kakšna je rešitev tega osnovnega problema?

2680 2009-04-15T06:06:20+00:00 3
 LogicalBranch
LogicalBranch
Edited question Npopoldan 54p23.5.20193tni 54trpopoldanni maj 2019 в 3:56
Programiranje
closures
javascript
loops
Popular videos
Learn Javascript Programming #4: For Loops (Looping Through Numbers, Arrays, Objects)
Learn Javascript Programming #4: For Loops (Looping Through Numbers, Arrays, Objects)
pred 5 leti
Closures in JavaScript | Inside a loop, inner function and setTimeoout
Closures in JavaScript | Inside a loop, inner function and setTimeoout
pred 4 leti
JavaScript closure inside loops
JavaScript closure inside loops
pred 5 leti
JavaScript Developer Full Course | JavaScript Developer Tutorial | JavaScript Tutorial | Simplilearn
JavaScript Developer Full Course | JavaScript Developer Tutorial | JavaScript Tutorial | Simplilearn
pred 1 letom
JavaScript DOM Exercises 02
JavaScript DOM Exercises 02
pred 1 letom
Typing Test | HTML, CSS &amp; JS | Step By Step Javascript Project
Typing Test | HTML, CSS & JS | Step By Step Javascript Project
pred 1 letom
#37 javascript Generate Random number (Math.random()) درس جافاسكربت
#37 javascript Generate Random number (Math.random()) درس جافاسكربت
pred 2 leti
Most Asked JavaScript Interview Questions | SetTimeout &amp; EventLoop | JS Interview Series
Most Asked JavaScript Interview Questions | SetTimeout & EventLoop | JS Interview Series
pred 1 letom
How To Make A Responsive PERSONAL PORTFOLIO Website Design [ HTML - CSS - JAVASCRIPT ] From Scratch
How To Make A Responsive PERSONAL PORTFOLIO Website Design [ HTML - CSS - JAVASCRIPT ] From Scratch
pred 1 letom
Create A Responsive Food / Restaurant Website Design Using HTML / CSS / JAVASCRIPT - From Scratch
Create A Responsive Food / Restaurant Website Design Using HTML / CSS / JAVASCRIPT - From Scratch
pred 1 letom
« Prejšnji
Naslednji »
This question has 1 odgovor in English, to read them log in to your account.
Solution / Answer
 harto
harto
Ndopoldan 17p15.4.20092tni 17trdopoldanni april 2009 в 6:18
2009-04-15T06:18:17+00:00
Več
Vir:
Uredi
#8977267

Težava je v tem, da je spremenljivka i v vsaki od vaših anonimnih funkcij vezana na isto spremenljivko zunaj funkcije.

Klasična rešitev: Zapiranje

Spremenljivko znotraj vsake funkcije želite vezati na ločeno, nespremenljivo vrednost zunaj funkcije:

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

Ker v javascriptu ni obsega blokov, temveč le obseg funkcij, z ovitjem ustvarjanja funkcije v novo funkcijo zagotovite, da vrednost "i" ostane takšna, kot ste načrtovali.


2015 Rešitev: forEach

Ker je funkcija Array.prototype.forEach relativno široko dostopna (v letu 2015), je vredno omeniti, da v primerih, ki vključujejo iteracijo predvsem nad poljem vrednosti, funkcija .forEach() zagotavlja čist in naraven način za pridobitev ločenega zaključka za vsako iteracijo. To pomeni, da lahko ob predpostavki, da imate neko vrsto polja, ki vsebuje vrednosti (reference DOM, predmete, karkoli), in da se pojavi težava z vzpostavitvijo povratnih klicev, značilnih za vsak element, naredite to:

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

Ideja je, da bo vsak klic funkcije povratne zveze, ki se uporablja z zanko .forEach, svoje lastno zaprtje. Parameter, posredovan tej opravi, je element polja, ki je značilen za določen korak iteracije. Če je uporabljen v asinhronem povratnem klicu, ne bo trčil z nobenim od drugih povratnih klicev, vzpostavljenih v drugih korakih iteracije.

Če delate v programu jQuery, vam podobno možnost omogoča funkcija $.each().


Rešitev ES6: let

ECMAScript 6 (ES6) uvaja novi ključni besedi let in const, ki imata drugačen obseg kot spremenljivke na osnovi var. Na primer, v zanki z indeksom, ki temelji na let, bo imela vsaka iteracija skozi zanko novo vrednost i, pri čemer je vsaka vrednost scoped znotraj zanke, zato bi vaša koda delovala, kot ste pričakovali. Obstaja veliko virov, vendar bi priporočil 2alityjevo objavo Block-scoping kot odličen vir informacij.

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

Pazite pa, da IE9-IE11 in Edge pred Edge 14 podpirajo let, vendar se zgoraj navedeno napačno izvaja (ne ustvarijo vsakič novega i, zato bi se vse zgornje funkcije prijavile 3, kot bi se, če bi uporabili var). Edge 14 to končno naredi pravilno.

 LogicalBranch
LogicalBranch
Edited answer Npopoldan 12p23.5.20193tni 12trpopoldanni maj 2019 в 4:03
2067
0
 Bjorn
Bjorn
Ndopoldan 50p15.4.20092tni 50trdopoldanni april 2009 в 6:10
2009-04-15T06:10:50+00:00
Več
Vir:
Uredi
#8977266

Poskusite:

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

Edit (2014):

Novejši odgovor o uporabi .bind je po mojem mnenju zdaj najboljši način za tovrstno početje. Obstaja tudi lo-dash/underscoreov _.partial, kadar ne potrebujete ali se ne želite ukvarjati z thisArg, ki ga uporablja bind.

 henser
henser
Edited answer Ndopoldan 23p22.5.20192tni 23trdopoldanni maj 2019 в 11:33
370
0
 jottos
jottos
Ndopoldan 29p15.4.20092tni 29trdopoldanni april 2009 в 6:18
2009-04-15T06:18:29+00:00
Več
Vir:
Uredi
#8977268

Vaš prvotni primer ni deloval, ker so se vse zapore, ki ste jih ustvarili v zanki, sklicevale na isti okvir. V bistvu imate tri metode na enem objektu z eno samo spremenljivko i. Vse so izpisale isto vrednost.

 Nae
Nae
Edited answer Npopoldan 18p26.12.20171tni 18trpopoldanni december 2017 в 8:27
8
0
Dodajte vprašanje
Kategorije
Vse
Tehnologija
Kultura / Rekreacija
Življenje / umetnost
Znanost
Strokovno
Poslovni
Uporabniki
Vse
New
Popular
1
Mansur Zakirov
Registered pred 1 dnem
2
Тагир Мамедов
Registered pred 3 dnevi
3
Алексей Толманов
Registered pred 3 dnevi
4
Valeriu Vodnicear
Registered pred 1 tednom
5
Alex Johnson
Registered pred 2 tednoma
DE
ES
FR
ID
JA
KO
PT
RO
RU
SL
TR
ZH
© kzen.dev 2023
Vir:
stackoverflow.com
na podlagi licence cc by-sa 3.0 z navedbo avtorstva