Mengapa saya dapat menambahkan properti bernama ke array seolah-olah itu adalah objek?

105

Dua cuplikan kode berbeda berikut ini tampaknya setara dengan saya:

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

dan

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

karena keduanya berperilaku sama, dan juga typeof(myArray) == typeof(myObjects)(keduanya menghasilkan 'objek').

Apakah ada perbedaan di antara varian ini?

prinzdezibel.dll
sumber

Jawaban:

131

Hampir semua yang ada di javascript adalah objek, jadi Anda dapat "menyalahgunakan" objek Array dengan menyetel properti arbitrer di atasnya. Ini harus dianggap berbahaya . Array adalah untuk data yang diindeks secara numerik - untuk kunci non-numerik, gunakan Object.

Berikut adalah contoh yang lebih konkret mengapa kunci non-numerik tidak "sesuai" dengan Array:

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

alert(myArray.length);

Ini tidak akan menampilkan '2', tetapi '0' - secara efektif, tidak ada elemen yang ditambahkan ke array, hanya beberapa properti baru yang ditambahkan ke objek array.

Paul Dixon
sumber
4
myArray.length mengembalikan indeks / kunci numerik dari elemen terakhir dalam array tetapi bukan jumlah elemen sebenarnya. Apakah properti objek Array tidak sama dengan nilai array?
Dasha Salo
1
Saya hanya mencoba untuk menggambarkan semantik yang dimaksudkan dari objek Array yang disalahgunakan jika Anda hanya memperlakukannya seperti objek biasa. Artikel terkait melakukan pekerjaan yang lebih baik :)
Paul Dixon
13
Lain kali seseorang mengatakan JavaScript adalah bahasa yang baik untuk dikembangkan, saya akan menunjukkan contoh ini kepadanya. Terima kasih.
Olivier Pons
@Olivier, apa yang Anda sebut sebagai "bug" juga bisa menjadi "fitur" yang luar biasa. Anda dapat menambahkan judul dan deskripsi ke array tanpa memengaruhi konten atau panjangnya dan tanpa harus membungkusnya dalam objek dengan title, descriptiondan itemsproperti. Itu semua tergantung pada seberapa baik Anda mengetahui bahasa tersebut dan bagaimana Anda menggunakannya.
tao
Menggunakan properti khusus pada Array tidak sepenuhnya salah. Apa yang salah mengharapkan mereka untuk bertindak sebagai anggota array setelah Anda melakukannya. Mereka adalah properti array, bukan anggota, karenanya tidak terpengaruh oleh metode array. Ini sebenarnya dikatakan oleh penulis artikel terkait di atas, di komentar. Sekarang, dalam semua keadilan, saya akan menyarankan untuk tidak melakukannya sebagai praktik, karena mungkin akan membingungkan orang yang menggunakan kode Anda. Atau, jika mereka baru memulai, itu akan menempatkan mereka di jalur yang berbahaya, dengan kekuatan sebagai contoh. Tetapi saya tidak akan mengatakan JavaScript itu buruk karena memungkinkan hal-hal yang paling tidak diharapkan untuk diizinkan.
tao
14

Dalam array JS adalah objek, hanya sedikit dimodifikasi (dengan beberapa fungsi lagi).

Fungsinya seperti:

concat
every   
filer
forEach
join
indexOf
lastIndexOf
map
pop
push
reverse
shift
slice
some
sort
splice
toSource
toString
unshift
valueOf 
Casey
sumber
Meskipun saya tidak berpikir semua fungsi yang terdaftar adalah built-in setiap implementasi JS, Anda mengerti maksudnya. Perbedaan lainnya adalah prototipe yang berbeda (yang diimplikasikan oleh fungsi ekstra tersebut).
Rashack
6

Saya pikir, saya terlalu metaforis dan samar dengan jawaban sebelumnya. Klarifikasi mengikuti.

Sebuah instance dari Array, Boolean, Date, Function, Number, RegExp, String adalah sebuah Object tetapi ditingkatkan dengan metode dan properti yang spesifik untuk setiap tipe. Misalnya, sebuah array memiliki lengthproperti yang telah ditentukan sementara objek umum tidak.

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

menampilkan

0
tidak terdefinisi

Secara intrinsik, juru bahasa FF Gecko juga membedakan antara Array dan Objek generik dengan perbedaan yang berbeda dalam mengevaluasi konstruksi bahasa.

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

menampilkan

satu dua tiga

[Objek Objek]

["satu dua tiga"]

4. toSource () lupakan saya! 

3 dan panjang saya! 

({0: "one", 1: "two", 2: "three", a: 4})

dan 0 1 2 adan 0 1 2 a.

Mengenai pernyataan bahwa semua objek adalah fungsi:

Tidaklah benar secara sintaksis maupun semantik untuk menggunakan instance objek arbitrer sebagai fungsi seperti 123()atau "abc"()atau []()atau {}()atau di obj()mana objada tipe selain Function, jadi objek arbitrer INSTANCE bukanlah a Function. Namun, jika diberi objek objdan tipenya Array, Boolean, Date, ..., bagaimana objbisa menjadi sebagai Array, Boolean, Date, ...? Apa itu Array, Boolean, Date, ...?

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

menampilkan

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]
}

Dalam setiap kasus, tanpa keraguan, tipe objek bermanifestasi sebagai functiondefinisi, oleh karena itu pernyataan bahwa semua objek adalah fungsi! (Lidah di pipi adalah bahwa saya sengaja mengaburkan dan mengaburkan perbedaan contoh objek dengan tipe itu! Namun, ini menunjukkan "Anda tidak dapat memiliki satu tanpa yang lain", Objek dan Fungsi! Kapitalisasi menekankan tipe sebagai menentang contoh.)

Baik paradigma fungsional dan objek tampaknya menjadi dasar untuk pemrograman dan penerapan primitif bawaan tingkat rendah interpreter JS, seperti Mathdan JSONdan true.

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

menampilkan

[object Math]

[object JSON]

(new Boolean(true))

Pada saat pengembangan Javascript, gaya pemrograman objek-sentris (OOP - gaya Pemrograman Berorientasi Objek - "s" adalah permainan kata-kata saya!) Sedang digemari dan interpreter juga dinamai dengan Java untuk memberikan kredibilitas yang lebih besar . Teknik pemrograman fungsional diturunkan ke ujian yang lebih abstrak dan esoterik yang mempelajari teori Automata, Fungsi Rekursif, Bahasa Formal, dll. Dan dengan demikian tidak cocok. Namun, kekuatan dari pertimbangan formal ini jelas terlihat dalam Javascript terutama seperti yang diterapkan di mesin Gecko FF (mis. .toSource()).


Definisi Objek untuk Fungsi sangat memuaskan karena didefinisikan sebagai relasi perulangan! didefinisikan menggunakan definisi itu sendiri!

function Function() { [native code] }
dan karena suatu fungsi adalah Objek, sentimen yang sama berlaku
function Object() { [native code] }.

Sebagian besar definisi lain tidak sesuai dengan nilai terminal statis. Namun, eval()adalah primitif yang sangat kuat sehingga String juga dapat menyematkan fungsionalitas arbitrer.

Perhatikan lagi, bahasa daerah yang digunakan di atas mengaburkan tipe objek dan perbedaan contoh.

Ekim
sumber
5

Segala sesuatu di JavaScript adalah objek selain tipe primitif.

Kode

var myArray = Array();

membuat instance dari objek Array sementara

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

membuat sebuah instance dari objek Object.

Coba kode berikut

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

Jadi Anda akan melihat perbedaannya adalah pada tipe konstruktor objek.

Instance dari objek Array akan berisi semua properti dan metode dari prototipe Array.

Dasha Salo
sumber
2

Perbedaan antara array dan objek lain di JavaScript. Meskipun array memiliki properti length yang diperbarui secara ajaib, untuk objek selain array, tidak ada cara untuk mengimplementasikan properti seperti itu.

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

Array digunakan untuk menyimpan sesuatu dengan indeks ordinal - gunakan seperti array tradisional, tumpukan, atau antrian. Objek adalah hash - gunakan untuk data yang memiliki kunci berbeda.

Parth Raval
sumber
2

Anda dapat menambahkan properti bernama ke hampir semua hal di javascript tetapi itu tidak berarti Anda harus melakukannya. Arraydi javascript harus digunakan sebagai daftar, jika Anda ingin menggunakan array asosiatif Objectsebagai gantinya.

Berhati-hatilah jika Anda benar-benar ingin menggunakan Arraydengan properti bernama alih-alih Objectproperti itu tidak akan dapat diakses dalam satu for...ofloop dan Anda mungkin juga mendapatkan hasil yang tidak diharapkan ketika JSON mengenkode untuk menyebarkannya. Lihat contoh di bawah ini di mana semua indeks non-numerik diabaikan:

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
sumber
-1

The {}-notation gula hanya sintaksis untuk membuat kode lebih bagus ;-)

JavaScript memiliki banyak konstruksi serupa seperti konstruksi fungsi, di mana function () hanyalah sinonim untuk

var Func = new Function("<params>", "<code>");
Dario
sumber
3
Konstruktor fungsi BUKAN merupakan sinonim untuk literal fungsi. Literal dibatasi secara leksikal sedangkan konstruktor bersifat global. {}adalah notasi objek literal, []adalah array literal, saya tidak yakin apa maksud dari jawaban Anda.
Juan Mendes
Selain itu, fungsi yang dideklarasikan tersedia sebelum kode apa pun dieksekusi, tugas yang menggunakan konstruktor Fungsi tidak tersedia hingga kode yang membuatnya dijalankan.
RobG