Perché posso aggiungere proprietà denominate a un array come se fosse un oggetto?


105

I seguenti due diversi frammenti di codice mi sembrano equivalenti:

var myArray = Array();
myArray['A'] = "Athens";
myArray['B'] = "Berlin";

e

var myObject = {'A': 'Athens', 'B':'Berlin'};

perché entrambi si comportano allo stesso modo, e anche typeof(myArray) == typeof(myObjects)(entrambi producono "oggetto").

C'è qualche differenza tra queste varianti?

Risposte:


131

Praticamente tutto in javascript è un oggetto, quindi puoi "abusare" di un oggetto Array impostando proprietà arbitrarie su di esso. Questo dovrebbe essere considerato dannoso però. Gli array sono per dati indicizzati numericamente: per chiavi non numeriche, usa un Object.

Ecco un esempio più concreto del motivo per cui i tasti non numerici non "si adattano" a un array:

var myArray = Array();
myArray['A'] = "Athens";
myArray['B'] = "Berlin";

alert(myArray.length);

Questo non mostrerà "2", ma "0" - in effetti, nessun elemento è stato aggiunto all'array, solo alcune nuove proprietà aggiunte all'oggetto dell'array.


4
myArray.length restituisce un indice / chiave numerico dell'ultimo elemento dell'array ma non il numero effettivo di elementi. Le proprietà dell'oggetto Array non sono le stesse dei valori dell'array?
Dasha Salo

1
Stavo solo cercando di illustrare che la semantica prevista dell'oggetto Array viene abusata se lo tratti come un oggetto normale. L'articolo collegato fa un lavoro migliore però :)
Paul Dixon

13
La prossima volta che qualcuno dice che JavaScript è un buon linguaggio con cui sviluppare, gli mostrerò questo esempio. Grazie.
Olivier Pons

@Olivier, quello che chiami un "bug" può anche essere una fantastica "funzionalità". È possibile aggiungere un apice e la descrizione per gli array senza influenzare il loro contenuto o la lunghezza e senza dover avvolgerli in oggetti con title, descriptione itemsle proprietà. Tutto dipende da quanto conosci la lingua e da come la usi.
tao

L'utilizzo di proprietà personalizzate su array non è intrinsecamente sbagliato. Ciò che è sbagliato è aspettarsi che agiscano come membri dell'array una volta che lo fai. Sono proprietà dell'array, non membri, quindi non sono influenzate dai metodi dell'array. Questo è in realtà detto dall'autore dell'articolo sopra collegato, nei commenti. Ora, in tutta franchezza, lo sconsiglierei come pratica, poiché probabilmente confonderà a morte le persone che usano il tuo codice. Oppure, se stanno appena iniziando, li metterà su un percorso pericoloso, con il potere dell'esempio. Ma non direi che JavaScript è cattivo perché consente cose che la maggior parte non si aspetta siano consentite.
tao

14

In JS gli array sono oggetti, solo leggermente modificati (con poche funzioni in più).

Funziona come:

concat
every   
filer
forEach
join
indexOf
lastIndexOf
map
pop
push
reverse
shift
slice
some
sort
splice
toSource
toString
unshift
valueOf 

Anche se non penso che tutte le funzioni elencate siano integrate in ogni implementazione JS, hai capito. L'altra differenza sarebbe un prototipo diverso (che è implicito da quelle funzioni extra).
Rashack

6

Io penso, anch'io metaforico e criptico con la risposta precedente. Segue un chiarimento.

Un'istanza di Array, Boolean, Date, Function, Number, RegExp, String è un Object ma migliorato con metodi e proprietà specifici per ogni tipo. Ad esempio, un array ha una lengthproprietà predefinita mentre gli oggetti generici no.

javascript:alert([].length+'\n'+{}.length)

visualizza

0
non definito

Intrinsecamente, l'interprete FF Gecko distingue anche tra array e oggetti generici con differenze distinte nella valutazione dei costrutti del linguaggio.

javascript:
  ra=[  "one",   "two",   "three"]; ra.a=4;
  ob={0:"one", 1:"two", 2:"three"}; ob.a=4;
  alert(
    ra            +"\n\n"+
    ob            +"\n\n"+
    ra.toSource() +"\n\n"+
    ra.a          +"\t .toSource() forgot me! \n\n"+
    ra.length     +"\t and my length! \n\n"+
    ob.toSource());
  ps=""; for(i in ra)ps+=i+" "; alert(ps);  /* NB .length is missing! */
  ps=""; for(i in ob)ps+=i+" "; alert(ps);

visualizzazione

uno due tre

[oggetto Oggetto]

["uno due tre"]

4 .toSource () mi ha dimenticato! 

3 e la mia lunghezza! 

({0: "uno", 1: "due", 2: "tre", a: 4})

e 0 1 2 ae 0 1 2 a.

Per quanto riguarda l'affermazione che tutti gli oggetti sono funzioni:

Non è né sintatticamente né semanticamente corretto utilizzare un'istanza oggetto arbitrario come una funzione come 123()o "abc"()o []()o {}()o obj()dove objè qualsiasi tipo diverso Function, quindi un oggetto GRADO arbitrario non è Function. Tuttavia, dato un oggetto objed è tipo come Array, Boolean, Date, ..., come è objvenuto ad essere come un Array, Boolean, Date, ...? Cos'è un Array, Boolean, Date, ...?

javascript:
    alert([Array, Boolean, Date, Function, 
              Number, Object, RegExp, String] . join('\n\n') );

visualizza

function Array() {
    [native code]
}

function Boolean() {
    [native code]
}

function Date() {
    [native code]
}

function Function() {
    [native code]
}

function Number() {
    [native code]
}

function Object() {
    [native code]
}

function RegExp() {
    [native code]
}

function String() {
    [native code]
}

In ogni caso, senza equivoci, il tipo di oggetto si manifesta come una functiondefinizione, da qui l'affermazione che tutti gli oggetti sono funzioni! (L'ironia è che ho intenzionalmente oscurato e offuscato la distinzione di un'istanza di oggetto con quella del suo tipo! Tuttavia, questo mostra "non puoi averne uno senza l'altro", Oggetto e Funzione! Le maiuscole enfatizzano il tipo come opposto all'istanza.)

Sia un paradigma funzionale che uno a oggetti sembrano essere fondamentali per la programmazione e l'implementazione delle primitive incorporate di basso livello dell'interprete JS, come Mathe JSONe true.

 javascript:alert([Math, JSON, true.toSource()].join("\n\n"));

visualizza

[object Math]

[object JSON]

(new Boolean(true))

Al tempo dello sviluppo di Javascript, uno stile di programmazione incentrato sugli oggetti (OOP - stile di programmazione orientata agli oggetti - la "s" è il mio gioco di parole!) Era in voga e l'interprete veniva battezzato allo stesso modo con Java per dargli maggiore credibilità . Le tecniche di programmazione funzionale furono relegate a esami più astratti ed esoterici studiando le teorie degli automi, delle funzioni ricorsive, dei linguaggi formali, ecc. E come tali non appetibili. Tuttavia, i punti di forza di queste considerazioni formali sono chiaramente evidenti in Javascript, in particolare come implementato nel motore Gecko di FF (cioè .toSource()).


La definizione di Oggetto per Funzione è particolarmente soddisfacente poiché è definita come una relazione di ricorrenza! definito usando la sua definizione!

function Function() { [native code] }
e poiché una funzione è un oggetto vale lo stesso sentimento
function Object() { [native code] }.

La maggior parte delle altre definizioni si interrompe su un valore terminale statico. Tuttavia, eval()è una primitiva particolarmente potente e quindi una String può anche incorporare funzionalità arbitrarie.

Notare ancora una volta che il vernacolo usato sopra oscura il tipo di oggetto e la distinzione tra istanze.


5

Tutto in JavaScript è un oggetto oltre ai tipi primitivi.

Il codice

var myArray = Array();

crea un'istanza dell'oggetto Array while

var myObject = {'A': 'Athens', 'B':'Berlin'};

crea un'istanza dell'oggetto Object.

Prova il codice seguente

alert(myArray.constructor)
alert(myObject.constructor)

Quindi vedrai che la differenza sta nel tipo di costruttore di oggetti.

L'istanza dell'oggetto Array conterrà tutte le proprietà e i metodi del prototipo Array.


2

La differenza tra gli array e gli altri oggetti in JavaScript. Sebbene gli array abbiano una proprietà length che si aggiorna magicamente, per oggetti diversi dagli array non c'è modo di implementare tale proprietà.

var arrName = [];
arrName[5] = "test";
arrName.length; // <- 6

Gli array vengono utilizzati per archiviare elementi con un indice ordinale: usali come un array, uno stack o una coda tradizionali. Un oggetto è un hash: usalo per i dati che hanno una chiave distinta.


2

Puoi aggiungere proprietà con nome a quasi tutto in javascript, ma ciò non significa che dovresti. Arrayin javascript dovrebbe essere usato come una lista, se vuoi usare Objectinvece un array associativo .

Fai attenzione che se vuoi davvero usare un Arraycon proprietà denominate invece di Objectquelle proprietà non sarà accessibile in un for...ofciclo e potresti anche ottenere risultati imprevisti quando lo codifichi JSON per passarlo. Vedi l'esempio di seguito in cui tutti gli indici non numerici vengono ignorati:

let arr = [];
let obj = {};

arr['name'] = 'John';
obj['name'] = 'John';

console.log(arr);    // will output [name: "John"]
console.log(obj);    // will output {name: "John"}

JSON.stringify(arr); // will return [] <- not what you expected
JSON.stringify(obj); // will return {"name":"John"}

-1

La {}-notazione è solo zucchero sintattico per rendere il codice più carino ;-)

JavaScript ha molti costrutti simili come la costruzione di funzioni, dove function () è solo un sinonimo di

var Func = new Function("<params>", "<code>");

3
Il costruttore della funzione NON è un sinonimo del valore letterale della funzione. Il valore letterale ha ambito lessicale mentre il costruttore è globale. {}è la notazione letterale dell'oggetto, []è un array letterale, non sono sicuro di quale sia il punto della tua risposta.
Juan Mendes

Inoltre, le funzioni dichiarate sono disponibili prima dell'esecuzione di qualsiasi codice, le assegnazioni che utilizzano il costruttore di funzioni non sono disponibili finché non viene eseguito il codice che le crea.
RobG,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.