Svantaggi nell'uso di "array associativi" in JavaScript

2

Sto lavorando con alcune persone che sono abituate a creare "array associativi" in JavaScript come questo:

var arr = new Array();
arr.prop_1 = "asdf";

o

arr['prop 2'] = "1234";

Funziona proprio come un oggetto perché lo è. È possibile utilizzare for...in loops e l'accesso alle proprietà va bene con un punto o una parentesi quadra. la mancanza di metodi di matrice nativa sembra non essere dispiaciuta. Lo trovo comunque semanticamente irritante. Forse sono schizzinoso, ma voglio una buona argomentazione per arrestare l'uso di questa sintassi, ma non riesco a capire come iniziare. Qualche suggerimento?

    
posta 1252748 21.11.2013 - 23:12
fonte

4 risposte

9

Quale pensi sia più pulito?

object = new Array();
object.prop1 = 1;
object.prop2 = 2;
object.prop3 = 3;

o

object = {
  prop1: 1,
  prop2: 2,
  prop3: 3
}

Inoltre, se fai qualcosa di simile:

if (object.length === undefined) object.length = 10
object.length // 0

Allora object.length sarà ancora 0, che non è sicuramente quello che ti aspetteresti. Potresti pensare che questo sia solo un falso esempio che non verrà mai nella vita reale, ma guarda questo:

words = 'You should join our club because it is a club'.split(' ')
obj = new Array()
words.forEach(function(x) {
  if (obj[x] === undefined) obj[x] = 0
  obj[x] ++
})
for (var x in obj) console.log(x, obj[x])

Questo registrerà:

You 1
should 1
join NaN // <-- oops
our 1
club 2
because 1
it 1
is 1
a 1

In alternativa, puoi fare un'analogia con qualsiasi altro oggetto, come una funzione:

object = function() {}
object.prop1 = 1;
// ...

Chiunque potrebbe dirti immediatamente che è sbagliato, e usare un array è sbagliato.

    
risposta data 21.11.2013 - 23:22
fonte
7

Questo non è un array associativo. Questo è un oggetto dell'array maltrattato. Funziona solo perché gli array sono anche oggetti in JavaScript.

Quando stai facendo arr.prop_1 = "asdf"; o arr['prop 2'] = "1234"; ciò che stai facendo in realtà è la patch di scimmia su un oggetto.

Le persone usano gli oggetti come mappe spesso - ma questo verrà risolto presto dal momento che ES6 (la nuova versione del JS standard è basata su) ha% tipi di% co_de.

Quando utilizzare una matrice

Se si dispone di dati sequenziali: un elenco di numeri, ad esempio

Quando utilizzare una mappa

Quando vuoi memorizzare una mappatura dei valori-chiave.

    
risposta data 21.11.2013 - 23:18
fonte
2

Funziona "come un oggetto" perché vicino a tutto in JS c'è un oggetto.

Osserva i seguenti incarichi di proprietà legittimi ma per lo più completamente inutili:

function doSomething(){};
doSomething.someProperty = 'bob';

6..someProperty = 'bob'; //(6). would have worked too

'bob'.someProperty = 'bob';

Qualsiasi oggetto può anche avere proprietà tramite notazione parentesi, che consente di nomi di proprietà non regolarmente consentiti dalle normali restrizioni JS var / property naming. Questo è molto utile per fare cose come mappare gli URL a metodi o oggetti.

Nel caso dei tuoi amici, ci sono due cose che stanno facendo in modo stupido.

  1. Stanno usando il costruttore di array quando dovrebbero usare un letterale di array. Non è un grosso problema ma crea inutili sovraccarichi e alcuni avvertono che qualcuno potrebbe scavalcare la funzione Array del costruttore, ma sarebbe una cosa davvero stupida da fare che verrebbe comunque notato nella maggior parte delle basi di codice. La convenzione generale se hai bisogno di un array JS è semplicemente fare questo.

    var arrayFoo = [];

  2. Serve a zero benefici per utilizzare un array per ciò che percepiscono come un comportamento associativo come un array, poiché qualsiasi oggetto in JS può avere proprietà assegnate in questo modo e anche gli array sono oggetti. L'utilizzo di un oggetto letterale rende l'intento più chiaro e non eredita tutti gli elementi dell'array che non verranno utilizzati con le proprietà dell'oggetto impostate con notazione della parentesi.

    var nameValuePairs = {
        'someValue': 'bob',
        anotherValue: 'joe',
        'string properties are like bracket notation' : 'bar'
    };
    

E ovviamente puoi aggiungerne altre quante ne vuoi:

nameValuePairs['some other value'] = 'bob 2';

Si noti che non è sempre un cattivo comportamento attaccare le proprietà alle funzionalità di JS che normalmente non vengono chiamate oggetti. Ad esempio, i costruttori di funzioni hanno spesso proprietà impostate direttamente su di essi. Questo è simile al modo in cui è possibile inserire metodi statici su una classe in Java o C #. Ad esempio, crei timestamp con new Date ma puoi anche analizzare i millisecondi in un oggetto data con Date.parse . Nelle giuste circostanze potrebbe essere sensato mettere anche delle proprietà extra su un array, ma io non ne prenderei l'abitudine.

JS ha solo due strutture dati. {} e [] . Potrebbe sembrare limitato, ma visto quanto sono flessibili e completi, non c'è davvero molto che non si possa fare prontamente con una combinazione dei due. Non c'è bisogno di array associativi perché i letterali degli oggetti hanno quello coperto.

Quindi, per farli smettere, direi loro che le loro intenzioni non sono chiare o peggiori, li fa sembrare JOB.

    
risposta data 22.11.2013 - 05:22
fonte
2

L'utilizzo dell'oggetto Array in questo modo avverte molto, molto male . Rimuove completamente i vantaggi della classe Array e non aggiunge alcun valore.

L'intero punto di utilizzo degli array è ... beh .. trattarli come array. In questo modo puoi accedere a gadget come push , pop , shift , splice , sort , join , .length ecc.

Considera solo cosa succede quando aggiungi poche proprietà al tuo array in questo modo:

var test = new Array();
test.prop1 = 'hi';
test.prop2 = 'ho';
test.prop3 = 'ha';

test.length; // returns 0
test.join() // returns ""
test.pop() // returns undefined ... and so on

Hai completamente cancellato la vera funzione di un array.

Anche il loop attraverso questa mostruosità è non banale , in quanto è necessario passare ogni proprietà attraverso hasOwnProperty per verificare se è una proprietà impostata, o è qualcosa proveniente da Array.prototype. - come Doorknob ha sottolineato che le proprietà interne dell'array non sono visibili.

Non ho intenzione di iniziare con ciò che accade quando qualcuno tenta di assegnare una proprietà chiamata length su questo oggetto, ecc.

Ora, c'è un modo giusto per memorizzare proprietà come questa, usando un oggetto semplice.

var test = {};
test.prop1 = 'hi';
test.prop2 = 'ho';
test.prop3 = 'ha';

Qui, puoi ancora eseguirne il loop recuperando le chiavi e i valori, ma la parte più importante di questa sintassi e per cosa viene usata spesso, è che puoi cercare direttamente il valore, senza eseguire il ciclo : %codice%. Questo è fantastico, perché non è necessario eseguire il looping di grandi oggetti / array per trovare la proprietà che si sta cercando.

Quindi ancora una volta - se vuoi memorizzare un gruppo di valori e trattarli come un array in cui puoi aggiungere / rimuovere elementi facilmente e usare test['prop1'] per controllare il numero di elementi ecc. - usa .length class.

Se vuoi accedere all'elemento direttamente con la chiave, e non hai bisogno di alcuna funzionalità dell'array (pensa a hashmap), usa Array semplice.

Ma per l'amor di Dio non utilizzare la classe Object per la tua base hashmap.

    
risposta data 22.11.2013 - 04:07
fonte

Leggi altre domande sui tag