Toon posts:

[JS] Scoping in een for-loop en functie

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik kom een probleem tegen met de volgende code: (test case)

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function Auto()
{
    this.onderdelen = ['test', 'bla', 'fiets'];

    this.test = function() {
        var self = this;

        var arr = new Array();
        for (var i = 0; i < this.onderdelen.length; i++) {
            // Add keyword item
            arr[arr.length] = [this.onderdelen[i], [], function() {
                self.testOnderdeel(self.onderdelen[i]);
            }];
        }
        return arr;
    }

    this.testOnderdeel = function(index) {
        alert( 'testOnderdeel index = ' + index);
    }
}

var kar = new Auto();
kar.test();
In [...] arr[arr.length] = [this.onderdelen[i] [...] gaat alles goed, maar in function() { self.testOnderdeel(self.onderdelen[i]); }]; verwijst i kennelijk naar de i die in het geheugen staat, waardoor deze altijd naar de laatste i (oftewel de index van het laatste element van de array waar ik doorheen loop) verwijst...

Heb al gezocht op GoT en Google, maar nog niks kunnen vinden. Weet iemand hier een oplossing voor?

Alvast bedankt!

[ Voor 7% gewijzigd door Verwijderd op 03-03-2006 14:20 ]


  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

for(var i in this.onderdelen) { ..
om zeker te zijn dat je alle elementen van this.onderdelen afloopt.
deze snap ik ook niet helemaal arr[arr.length], als je iets wil toevoegen gebruik je array.push().
Heb je misschien een testpagina waarop het probleem duidelijker wordt?

oprecht vertrouwen wordt nooit geschaad


  • André
  • Registratie: Maart 2002
  • Laatst online: 08-04 16:23

André

Analytics dude

En als je new er bij gebruikt dan?
code:
1
arr[arr.length] = [this.onderdelen[i], [], new function() {

Verwijderd

Topicstarter
André schreef op vrijdag 03 maart 2006 @ 15:00:
En als je new er bij gebruikt dan?
code:
1
arr[arr.length] = [this.onderdelen[i], [], new function() {
Lijkt hier niks uit te halen...

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Die i is inderdaad een referentie naar de i die je daar in de loop gebruikt; volkomen logisch dus; is op te lossen door de i weer te scopen, bijvoorbeeld met een hulpfunctie:
JavaScript:
1
2
3
4
5
6
7
8
arr[arr.length] = [this.onderdelen[i], [], makeFunction(this, i)];

...

function makeFunction(self, i)
{
    return function() { self.testOnderdeel(self.onderdelen[i]); }
}

voordeel is ook dat de self = this dan ook overbodig is

[ Voor 8% gewijzigd door crisp op 03-03-2006 15:19 ]

Intentionally left blank


Verwijderd

Topicstarter
Atgast schreef op vrijdag 03 maart 2006 @ 14:48:
for(var i in this.onderdelen) { ..
om zeker te zijn dat je alle elementen van this.onderdelen afloopt.
deze snap ik ook niet helemaal arr[arr.length], als je iets wil toevoegen gebruik je array.push().
Heb je misschien een testpagina waarop het probleem duidelijker wordt?
De array bestaat enkel uit numerieke keys, dus for (var i in this.onderdelen) { [...] } lijkt me niet essentiëel.

In mijn ervaring werkt arr[arr.length] beter dan array.push()... Misschien dat ik .push() niet goed heb gebruikt, maar arr[arr.length] werkt perfect.

Test page kan los maken, maar heb ik niet, de code is deel van een groot project. Ik denk echter dat dit eerder een conceptueel probleem is, als er aan bovenstaande code iets specifieks niet duidelijk is wil ik dit graag verhelderen.

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Atgast schreef op vrijdag 03 maart 2006 @ 14:48:
for(var i in this.onderdelen) { ..
om zeker te zijn dat je alle elementen van this.onderdelen afloopt.
Kan, maar dan moet je wel checken of je toevallig geen prototyped methods meepakt ;)
deze snap ik ook niet helemaal arr[arr.length], als je iets wil toevoegen gebruik je array.push().
Heb je misschien een testpagina waarop het probleem duidelijker wordt?
IE5 ondersteund bijvoorbeeld geen push() (en die moet je dan dus prototypen :P); feitelijk is er echter geen belemmering om arr[arr.length] te gebruiken ipv de push() method.
André schreef op vrijdag 03 maart 2006 @ 15:00:
En als je new er bij gebruikt dan?
code:
1
arr[arr.length] = [this.onderdelen[i], [], new function() {
Je referentie naar je object ('this' binnen de functie) wordt dan problematisch; de closure is hier wat dat betreft essentieel... (ik neem aan dat je new Function() bedoelt als in de function-constructor, als je new function() gebruikt wordt de functie meteen uitgevoerd en het resultaat gebruikt als constructor :P)

[ Voor 9% gewijzigd door crisp op 03-03-2006 15:21 ]

Intentionally left blank


Verwijderd

Topicstarter
Thanks, crisp. Alles werkt nu naar behoren.

Best een hoop extra code trouwens, ik vind het wel erg suf dat het niet op een makkelijkere manier kan in JavaScript.

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Verwijderd schreef op vrijdag 03 maart 2006 @ 15:21:
Thanks, crisp. Alles werkt nu naar behoren.

Best een hoop extra code trouwens, ik vind het wel erg suf dat het niet op een makkelijkere manier kan in JavaScript.
Tsja, hoe had je het dan gedacht? Als je er over nadenkt zit dit best logisch in elkaar en flexibeler kan je het haast niet krijgen. It's all in de scope-chain...

Intentionally left blank


  • André
  • Registratie: Maart 2002
  • Laatst online: 08-04 16:23

André

Analytics dude

Het kan wel korter met een eval() volgens mij, maar ik denk niet dat je dat wil :)
Pagina: 1