[JS] Var declaratie gaat de mist in

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Carharttguy
  • Registratie: Juli 2010
  • Laatst online: 04-07 23:09
Hallo iedereen

Ik word er gek van, misschien is het al wat te laat, maar een simpele variabele declareren gaat nu al de mist in. Ik heb deze code:

code:
1
<script>var rates, currencies; rates[0] = 1; currencies[0] = 'EUR'; </script><


In FF ontwikkelaarsmodus krijg ik een typeError: rates not defined.
Als ik die lijn door JSLint haal, krijg ik dit:
Expected 'rates' at column 0, not column 23.
var rates, currencies; rates[0] = 1; currencies[0] = 'EUR';
line 0 column 37
Expected 'currencies' at column 0, not column 37.
var rates, currencies; rates[0] = 1; currencies[0] = 'EUR';
Ik doe waarschijnlijk iets belachelijks mis, maar wat?
Heb ook al geprobeerd om de variables apart te declareren, maar dat geeft geen verschil.

Acties:
  • 0 Henk 'm!

  • xyanide
  • Registratie: September 2006
  • Laatst online: 23:28
Moet je niet eerst rates als array initializeren?

var rates = [];
rates[0] = 1;

Dus:
code:
1
var rates = [], currencies = []; rates[0] = 1; currencies[0] = 'EUR';

[ Voor 37% gewijzigd door xyanide op 29-08-2015 21:56 ]


Acties:
  • 0 Henk 'm!

  • Shineless
  • Registratie: November 2010
  • Laatst online: 09-12-2022
xyanide schreef op zaterdag 29 augustus 2015 @ 21:55:
Moet je niet eerst rates als array initializeren?

var rates = [];
rates\[0] = 1;

Dus:
code:
1
var rates = [], currencies = []; rates[0] = 1; currencies[0] = 'EUR';
Dit dus.
Wanneer je variable declareert zonder ze een waarde te geven, komen ze automagisch op "undefined" te staan. En je kan het eerste element van "undefined" niet setten ;) .

During the day I'm tired, because I'm a super hero at night.


Acties:
  • 0 Henk 'm!

  • Zoefff
  • Registratie: September 2001
  • Laatst online: 21:01

Zoefff

❤ 

En voor de volledigheid; je kan de array natuurlijk meteen vullen, je hoeft hem niet eerst te declareren en daarna te vullen. Kan ook op 1 regel, maar leesbaarheid gaat al snel boven het aantal regels als je 't mij vraagt. Dus:

JavaScript:
1
2
3
4
5
6
7
8
9
var rates = [
    1,
    42
];

var currencies = [
    'EUR',
    'GBP'
];


FotoblogWerkaandemuur.nlMoestuincursus.nlTwitter


Acties:
  • 0 Henk 'm!

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

En technisch gezien:

Een variabele declareren zonder value geeft em undefined als value. Als dan de nulde index probeert te zetten met [0], probeer je eigenlijk de property `0` te zetten. Undefined is een speciale value die (net als null) geen properties heeft, en ook geen properties erbij kan krijgen.

Zou je dit in een browser gieten, zou ie wrs zoiets zeggen als
"Cannot set property 0 of undefined".

Disclaimer: uit m'n hoofd :)


@xyanide
Jouw oplossing is suboptimaal, dus even voor jou: als je een array leeg initialiseert, en dan item #0 opeens gaat vullen, loopt het verwachte aantal items niet meer in sync met de property `length`. Immers, je zet met [0] een doodnormale property, en je mag er niet vanuit gaan dat er magie in javascript zit die daar wat mee doet. Want wat zou ie moten doen als je na initialisatie item #23761 erin denkt te zetten? ;)

[ Voor 30% gewijzigd door _Thanatos_ op 02-09-2015 03:06 ]

日本!🎌


Acties:
  • 0 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 22:49
_Thanatos_ schreef op woensdag 02 september 2015 @ 03:03:
[....] @xyanide
Jouw oplossing is suboptimaal, dus even voor jou: als je een array leeg initialiseert, en dan item #0 opeens gaat vullen, loopt het verwachte aantal items niet meer in sync met de property `length`. Immers, je zet met \[0] een doodnormale property, en je mag er niet vanuit gaan dat er magie in javascript zit die daar wat mee doet. Want wat zou ie moten doen als je na initialisatie item #23761 erin denkt te zetten? ;)
Dat is alleen niet hoe browsers er mee omgaan, zie bijv. https://jsfiddle.net/aktvud4v/ ;)

Of om de standaard er even bij te pakken:
[...]The length property of this Array object is a data property whose value is always numerically greater than the name of every deletable property whose name is an array index.[...]
en aangezien 23761 uit jouw voorbeeld een deletable name is.

[ Voor 21% gewijzigd door Caelorum op 02-09-2015 09:09 ]


Acties:
  • 0 Henk 'm!

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

Dat is wel ES5, dus nog vrij recent, in browser-termen ;)

Hoe dan ook, het is bad practise om een index te vullen van een array die die index niet heeft. Items toevoegen aan een array doe je met push() en verwijderen met bijv met splice(). Als je ineens [348972] gaat schrijven, en de length wordt wél geupdate, dan breekt het het itereren door de array, omdat je dan begint met 348971x undefined. Op zich niet erg, behalve dat het een performance-issue kan veroorzaken en je code moet er tegen kunnen.

Ik ben ook heel benieuwd hoe functies als .map() en .reduce() hiermee omgaan :X (die zijn ES5, dus je kunt in elk geval uitgaan van de aangehaalde spec)

[ Voor 13% gewijzigd door _Thanatos_ op 02-09-2015 10:13 ]

日本!🎌


  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
_Thanatos_ schreef op woensdag 02 september 2015 @ 10:11:
Dat is wel ES5, dus nog vrij recent, in browser-termen ;)
Dat gedeelte van ES5 is paving cowpath t.o.v. hoe de eerdere implementaties van ES3 werken. Is niets nieuws of vreemds zijn en is al heel lang zo.
_Thanatos_ schreef op woensdag 02 september 2015 @ 10:11:
Ik ben ook heel benieuwd hoe functies als .map() en .reduce() hiermee omgaan :X (die zijn ES5, dus je kunt in elk geval uitgaan van de aangehaalde spec)
De map, reduce, forEach etc. methods zijn allemaal op basis van hetzelfde concept van iteratie over een array opgezet en dat concept ligt vast in de standaard, waar dit wederom een stukje paving cowpath t.o.v. ES3 implementaties is.


Als je echt rare dingen omtrent array indices wilt zien, kijk dan eens naar het volgende:

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
var arr = [ "a", "b", "c" ];

delete arr[1];
console.log( arr.length, arr ); // 3, [ "a", undefined, "c" ]

delete arr[2];
console.log( arr.length, arr ); // 3, [ "a", undefined, undefined ]

arr.length = 1;
console.log( arr.length, arr ); // 1, [ "a" ]

arr.length = 2;
console.log( arr.length, arr ); // 2, [ "a", undefined ]

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

Dat is nog raarder ja, maar voor de semantiek (en daarmee leesbaarheid) gebruik ik dus liever functies als push() en splice() om elementen toe te voegen/te verwijderen.

日本!🎌


  • xyanide
  • Registratie: September 2006
  • Laatst online: 23:28
array[0] om een variabele te setten zonder dat je weet of op die positie al een waarde zit is natuurlijk niet de standaard manier. rates.push(item) is hierin de gewenste manier.

Mijn antwoord was primair gebaseerd op zijn code werkend krijgen en zorgen dat hij snapt dat je niet zomaar iets ergens in kan stoppen als het nog niet geïnitialiseerd is :-).

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 22:49
_Thanatos_ schreef op donderdag 03 september 2015 @ 10:52:
Dat is nog raarder ja, maar voor de semantiek (en daarmee leesbaarheid) gebruik ik dus liever functies als push() en splice() om elementen toe te voegen/te verwijderen.
Op zich is daar niets raars aan. In de standaard is vastgelegd dat het setten van length naar een waarde minder dan het aantal waardes in de array, de array truncate. Andersom overigens niet. De array groeit niet als je de length hoger zet dan de lengte van de array. Alleen de length property klopt dan niet meer met de daadwerkelijke lengte van de array. Niet dat je daar makkelijk tegenaan loopt overigens, maar voorbeeld van R4gnax is dan wel makkelijk te begrijpen.

En om op de 3e editie terug te komen:
[...]
15.4.5.1 [[Put]] (P, V) Array objects use a variation of the [[Put]] method used for other native ECMAScript objects (8.6.2.2).
Assume A is an Array object and P is a string.
When the [[Put]] method of A is called with property P and value V, the following steps are taken:
1. Call the [[CanPut]] method of A with name P.
2. If Result(1) is false, return.
3. If A doesn’t have a property with name P, go to step 7.
4. If P is "length", go to step 12.
5. Set the value of property P of A to V.
6. Go to step 8.
7. Create a property with name P, set its value to V and give it empty attributes.
8. If P is not an array index, return.
9. If ToUint32(P) is less than the value of the length property of A, then return.
10. Change (or set) the value of the length property of A to ToUint32(P)+1.
11. Return. 12. Compute ToUint32(V).
13. If Result(12) is not equal to ToNumber(V), throw a RangeError exception.
14. For every integer k that is less than the value of the length property of A but not less than Result(12), if A itself has a property (not an inherited property) named ToString(k), then delete that property.
- 98
15. Set the value of property P of A to Result(12).
16. Return.

15.4.5.2 length The length property of this Array object is always numerically greater than the name of every property whose name is an array index.
The length property has the attributes { DontEnum, DontDelete }.
[..]
Dat is dus hetzelfde gebleven. Je mag het zelf nalopen met een lege array, met lengte 0 en het zetten van positie 3 op "test".

Komen we op het punt van arrays, die zijn niet heel veel anders dan objecten. De enige reden waarom we vierkante haken gebruiken is omdat je niet kan zeggen: a = {}; a.0 = 1, maar a.[0] = 1 kan wel.
Zelfs de length property komt van object af, al heeft die in arrays een iets andere invulling.

[ Voor 56% gewijzigd door Caelorum op 03-09-2015 19:03 ]


Acties:
  • 0 Henk 'm!

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

Hoe het ook zij, ik zou dat soort onsemantisch gedrag graag scharen onder "the bad parts". Javascript kent veel meer constructies die technisch gezien verklaarbaar en correct zijn, maar kun je beter vermijden om jezelf kopzorgen te besparen, nu en/of in de toekomst.

日本!🎌


Acties:
  • 0 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 22:49
Het is maar wat je onsemantisch noemt. De . is niets ander dan ['']. Dus pietje.test zou je ook als piets['test'] kunnen schrijven. Objecten zijn in die zin gewoon dictionaries en juist de . is een speciaal geval en niet de array accessor. Daarnaast is het geval van length iets logischer als je meeneemt dat het een dictionary is, want dan snap je ook waarom het zo eenvoudig is om de 'array' te resizen en waarom het niet de daadwerkelijke grootte hoeft te representeren.
Overigens.. in mijn vorige voorbeeld gaf ik aan dat a.[0] wel kan, maar dit moet uiteraard a[0] of a['0'] zijn.

[ Voor 53% gewijzigd door Caelorum op 04-09-2015 18:36 ]

Pagina: 1