2015-09-13 12 views
7

Sto lavorando tramite The Principles of Object-Oriented Javascript e sono confuso dall'uso di Zakas di una chiave con nome all'interno di un array (anziché all'interno di un oggetto). Vedere commento:Utilizzo di chiavi con nome in un array JS

function EventTarget() {} 

EventTarget.prototype = { 

    constructor: EventTarget, 

    addListener: function(type, listener) { 

     if (!this.hasOwnProperty("_listeners")) { 
      // Why isn't this: `this._listeners = {};` 
      this._listeners = []; 
     } 

     if (typeof this._listeners[type] === "undefined") { 
      this._listeners[type] = []; 
     } 

     this._listeners[type].push(listener); 
    }, 

    // more stuff 
} 

var target = new EventTarget(); 
target.addListener("message", function(event) { 
    console.log("Message is " + event.data); 
}); 

suo codice funziona bene (come avviene se si sostituisce l'array per un oggetto letterale), ma la mia comprensione è che si dovrebbe usare un oggetto se si vuole accedere ai contenuti in base al nome. Da array article on w3schools:

Molti linguaggi di programmazione supportano gli array con indici denominati.
Gli array con indici nominati sono chiamati array associativi (o hash).
JavaScript non non matrici di supporto con indici nominati.
In JavaScript, array utilizzare sempre gli indici numerati .

C'è una buona ragione per cui Zakas ha utilizzato un array come questo? Puoi spiegarlo per favore? In alternativa, è qualcosa che dovrei inviare a the errata?

+0

Questo codice è corretto se 'type' è intero – hindmost

+0

Questo codice funziona ancora perché sta impostando le proprietà sull'oggetto array, non sull'array effettivo. Controllare 'Object.getOwnPropertyNames (this._listeners)' e quindi 'Object.keys (this._listeners)'. 'this._listeners' dovrebbe essere un oggetto, non un array. – usandfriends

+0

@hindmost: il codice è corretto (nel senso che è funzionale) anche se 'type' * non è * un intero (e sembra piuttosto probabile che non lo sia, molto più probabilmente una stringa come' "click" '). –

risposta

5

L'unica ragione che posso vedere è: persone che confondono. JavaScript non impone nulla, in realtà, e dal momento che tutto è un oggetto, puoi fare praticamente quello che vuoi. Questo ragazzo sta usando una matrice per memorizzare le proprietà denominate, ma potrebbe benissimo aver usato una funzione o qualsiasi altra cosa!

Edit: quasi tutto è un oggetto (sarebbe verificato a me che qualcuno potrebbe tentare di impostare una proprietà su undefined, dal momento che uno degli errori più comuni in JavaScript è TypeError : undefined is not an objectsospira JavaScript, perché lo sono. facendo questo a noi?

+1

" tutto è un oggetto ". Non tutto! – undefined

+1

Undefined non è un oggetto ... 'typeof undefined ===" undefined "' – usandfriends

2

c'è una buona ragione che Zakas utilizzato un array come questo?

Dal codice citato, non riesco a pensare a una sola, no. Lui non sta usando il f agisci che _listeners si riferisce a un array. Francamente sembra proprio un errore di battitura. Poiché funziona (poiché gli array normali di JavaScript sono oggetti), l'errore di battitura non è stato rilevato. Bene, finché non l'hai preso. :-)

A meno che non ci sia un codice che non hai citato che viene poi aggiunta enries matrice * a tale matrice, non c'è alcun motivo per utilizzare un array lì (e forse un paio di ragioni per non).

* "array entry" = proprietà la cui chiave è un indice di array . Quindi cos'è un "indice di array"? "Un nome di proprietà stringa P è un indice di matrice se e solo se ToString(ToUint32(P)) è uguale a P e ToUint32(P) non è uguale a 232−1." (spec)

2

Gli array sono solo oggetti speciali ....

a=[] 
a[7]=9 
a["abc"]=20 
a["xxx"]=30 
for (i in a) console.log("value",i,a[i]) 

Uscita;

value 7 9 
value abc 20 
value xxx 30 
0

Sono propenso a dire che è un errore di battitura, ma in off-chance si è inteso, quindi il seguente è l'unico caso d'uso funzionale posso venire con ... (avvertimento: maggio dividere opinione).

Dato che un pattern Observer/evento è un concetto generico che potrebbe essere applicato a qualsiasi oggetto e la "privato" (indicato con la sottolineatura) _listeners proprietà sarà probabilmente mai bisogno di essere conosciuto circa dal bersaglio - poi è discutibile che i dati che contiene siano superflui per l'oggetto stesso.

Vale a dire, probabilmente non è desiderabile trasmettere questo tipo di dati se l'oggetto di destinazione viene serializzato. L'esempio che segue illustra come il JSON serializzatore ignora le proprietà di matrice non-numerici in foo.baz - simile nel proprio esempio, tutti i dati di eventi associati sarebbero stati rimossi:

var foo = { 
    bar: {}, 
    baz: [] 
}; 

foo.bar['p1'] = foo.baz['p1'] = 1; 
foo.bar['p2'] = foo.baz['p2'] = 2; 

console.log(JSON.stringify(foo)); // {"bar":{"p1":1,"p2":2},"baz":[]} 
Problemi correlati