Warum kann ich einem Array benannte Eigenschaften hinzufügen, als wäre es ein Objekt?

105

Die folgenden zwei verschiedenen Codefragmente scheinen mir gleichwertig zu sein:

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

und

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

weil sie sich beide gleich verhalten und auch typeof(myArray) == typeof(myObjects)(beide ergeben 'Objekt').

Gibt es einen Unterschied zwischen diesen Varianten?

prinzdezibel
quelle

Antworten:

131

Praktisch alles in Javascript ist ein Objekt, so dass Sie ein Objekt "missbrauchen" können Array- Objekt indem Sie beliebige Eigenschaften festlegen. Dies sollte jedoch als schädlich angesehen werden . Arrays sind für numerisch indizierte Daten vorgesehen. Verwenden Sie für nicht numerische Schlüssel ein Objekt.

Hier ist ein konkreteres Beispiel, warum nicht numerische Schlüssel nicht in ein Array "passen":

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

alert(myArray.length);

Dies zeigt nicht '2' an, sondern '0' - effektiv wurden dem Array keine Elemente hinzugefügt, sondern nur einige neue Eigenschaften, die dem Array-Objekt hinzugefügt wurden.

Paul Dixon
quelle
4
myArray.length gibt einen numerischen Index / Schlüssel des letzten Elements im Array zurück, jedoch nicht die tatsächliche Anzahl der Elemente. Sind die Eigenschaften des Array-Objekts nicht mit den Array-Werten identisch?
Dasha Salo
1
Ich habe nur versucht zu veranschaulichen, dass die beabsichtigte Semantik des Array-Objekts missbraucht wird, wenn Sie es einfach wie ein reguläres Objekt behandeln. Der verlinkte Artikel macht einen besseren Job :)
Paul Dixon
13
Wenn jemand das nächste Mal sagt, dass JavaScript eine gute Sprache für die Entwicklung ist, zeige ich ihm dieses Beispiel. Danke dir.
Olivier Pons
@Olivier, was Sie einen "Bug" nennen, kann auch eine großartige "Funktion" sein. Sie können eine Pünktchen und Beschreibung Felder hinzuzufügen , ohne dessen Inhalt oder Länge zu beeinflussen und ohne mit ihnen in Objekten zu wickeln title, descriptionund itemsEigenschaften. Es hängt alles davon ab, wie gut Sie die Sprache kennen und wie Sie sie verwenden.
Tao
Die Verwendung benutzerdefinierter Eigenschaften für Arrays ist nicht von Natur aus falsch. Was falsch ist, ist zu erwarten, dass sie als Array-Mitglieder fungieren, sobald Sie dies tun. Sie sind Array-Eigenschaften, keine Mitglieder und daher von Array-Methoden nicht betroffen. Dies wird tatsächlich vom Autor des oben verlinkten Artikels in den Kommentaren gesagt. Nun, fairerweise würde ich als Praxis davon abraten, da es wahrscheinlich die Leute verwirren wird, die Ihren Code verwenden. Oder wenn sie gerade erst anfangen, werden sie durch Beispielkraft auf einen gefährlichen Weg gebracht. Aber ich würde nicht sagen, dass JavaScript schlecht ist, weil es Dinge erlaubt, von denen die meisten nicht erwarten, dass sie erlaubt sind.
Tao
14

In JS-Arrays handelt es sich um Objekte, die nur geringfügig geändert wurden (mit einigen weiteren Funktionen).

Funktionen wie:

concat
every   
filer
forEach
join
indexOf
lastIndexOf
map
pop
push
reverse
shift
slice
some
sort
splice
toSource
toString
unshift
valueOf 
Casey
quelle
Obwohl ich nicht denke, dass alle aufgelisteten Funktionen in jeder JS-Implementierung integriert sind, haben Sie den Punkt verstanden. Der andere Unterschied wäre ein anderer Prototyp (was durch diese zusätzlichen Funktionen impliziert wird).
Rashack
6

Ich denke, ich bin zu metaphorisch und kryptisch mit vorheriger Antwort. Klarstellung folgt.

Eine Instanz von Array, Boolean, Date, Function, Number, RegExp, String ist ein Objekt, das jedoch um Methoden und Eigenschaften erweitert wurde, die für jeden Typ spezifisch sind. Ein Array verfügt beispielsweise über eine vordefinierte lengthEigenschaft, während dies bei generischen Objekten nicht der Fall ist .

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

Anzeigen

0
nicht definiert

Eigentlich unterscheidet der FF-Gecko-Interpreter auch zwischen Arrays und generischen Objekten mit deutlichen Unterschieden bei der Bewertung von Sprachkonstrukten.

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);

Anzeigen

eins zwei drei

[Objekt Objekt]

["eins zwei drei"]

4 .toSource () hat mich vergessen! 

3 und meine Länge! 

({0: "eins", 1: "zwei", 2: "drei", a: 4})

und 0 1 2 aund 0 1 2 a.

In Bezug auf die Aussage, dass alle Objekte Funktionen sind:

Es ist weder syntaktisch noch semantisch korrekt, eine beliebige Objektinstanz als Funktion wie 123()oder "abc"()oder []()oder {}()oder obj()wo objein anderer Typ als ist Function, zu verwenden, sodass ein beliebiges Objekt INSTANCE kein a ist Function. Allerdings ist es eine Aufgabe gegeben objund es Typ als Array, Boolean, Date, ..., wie kam objkommen als zu sein Array, Boolean, Date, ...? Was ist ein Array, Boolean, Date, ...?

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

Anzeigen

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 jedem Fall manifestiert sich der Objekttyp ohne Mehrdeutigkeit als functionDefinition, daher die Aussage, dass alle Objekte Funktionen sind! (Die Zunge in der Wange ist, dass ich absichtlich die Unterscheidung einer Objektinstanz mit der ihres Typs verdeckt und verwischt habe! Dennoch zeigt dies "Sie können keine ohne die andere haben", Objekt und Funktion! Die Großschreibung betont den Typ als gegen Instanz.)

Sowohl ein Funktions- als auch ein Objektparadigma scheinen für die Programmierung und Implementierung der integrierten Grundelemente auf niedriger Ebene des JS-Interpreters wie Mathund JSONund von grundlegender Bedeutung zu sein true.

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

Anzeigen

[object Math]

[object JSON]

(new Boolean(true))

Zum Zeitpunkt der Entwicklung von Javascript war ein objektzentrierter Programmierstil (OOPs - Object Oriented Programming Style - das "'s" ist mein eigenes Wortspiel!) In Mode und der Interpreter wurde ähnlich mit Java getauft, um ihm mehr Glaubwürdigkeit zu verleihen . Funktionale Programmiertechniken wurden zu abstrakteren und esoterischeren Untersuchungen verbannt, die die Theorien von Automaten, rekursiven Funktionen, formalen Sprachen usw. studierten, und als solche nicht so schmackhaft. Die Stärken dieser formalen Überlegungen zeigen sich jedoch deutlich in Javascript, insbesondere in der Gecko-Engine von FF (dh .toSource()).


Die Objektdefinition für Funktion ist besonders zufriedenstellend, da sie als Wiederholungsrelation definiert ist! definiert mit seiner eigenen Definition!

function Function() { [native code] }
und da eine Funktion ein Objekt ist, gilt das gleiche Gefühl für
function Object() { [native code] }.

Die meisten anderen Definitionen basieren auf einem statischen Endwert. Ist eval()jedoch ein besonders leistungsfähiges Grundelement und daher kann ein String auch beliebige Funktionen einbetten.

Beachten Sie erneut, dass die oben verwendete Umgangssprache den Objekttyp und die Instanzunterscheidung verdeckt.

Ekim
quelle
5

Alles in JavaScript ist ein Objekt außer primitiven Typen.

Der Code

var myArray = Array();

Erstellt eine Instanz des Array-Objekts während

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

Erstellt eine Instanz des Objektobjekts.

Versuchen Sie den folgenden Code

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

Sie werden also sehen, dass der Unterschied in der Art des Objektkonstruktors liegt.

Die Instanz des Array-Objekts enthält alle Eigenschaften und Methoden des Array-Prototyps.

Dasha Salo
quelle
2

Der Unterschied zwischen den Arrays und den anderen Objekten in JavaScript. Während Arrays eine magisch aktualisierte Längeneigenschaft haben, gibt es für andere Objekte als die Arrays keine Möglichkeit, eine solche Eigenschaft zu implementieren.

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

Array werden verwendet, um Dinge mit einem Ordnungsindex zu speichern - verwenden Sie ihn wie ein herkömmliches Array, einen Stapel oder eine Warteschlange. Ein Objekt ist ein Hash - verwenden Sie es für Daten mit einem bestimmten Schlüssel.

Parth Raval
quelle
2

Sie können fast allem in Javascript benannte Eigenschaften hinzufügen, aber das bedeutet nicht, dass Sie dies tun sollten. Arrayin Javascript sollte als Liste verwendet werden, wenn Sie Objectstattdessen ein assoziatives Array verwenden möchten .

Beachten Sie, dass, wenn Sie wirklich eine Arraymit benannten Eigenschaften anstelle Objectdieser Eigenschaften verwenden möchten, in einer for...ofSchleife nicht auf sie zugegriffen werden kann und Sie möglicherweise auch unerwartete Ergebnisse erhalten, wenn JSON sie codiert, um sie weiterzugeben. Siehe Beispiel unten, in dem alle nicht numerischen Indizes ignoriert werden:

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"}
resu
quelle
-1

Die {}-notation ist nur syntaktischer Zucker, um den Code schöner zu machen ;-)

JavaScript hat viele ähnliche Konstrukte wie die Konstruktion von Funktionen, wobei function () nur ein Synonym für ist

var Func = new Function("<params>", "<code>");
Dario
quelle
3
Der Funktionskonstruktor ist KEIN Synonym für das Funktionsliteral. Das Literal hat einen lexikalischen Gültigkeitsbereich, während der Konstruktor global ist. {}ist eine wörtliche Objektnotation, []ist ein wörtliches Array, ich bin mir nicht sicher, worum es bei Ihrer Antwort geht.
Juan Mendes
Außerdem sind deklarierte Funktionen verfügbar, bevor Code ausgeführt wird. Zuweisungen mit dem Funktionskonstruktor sind erst verfügbar, wenn der Code, der sie erstellt, ausgeführt wird.
RobG