Jadi saya bermain-main beberapa hari yang lalu hanya untuk melihat dengan tepat bagaimana tugas massal bekerja di JavaScript.
Pertama saya mencoba contoh ini di konsol:
a = b = {};
a.foo = 'bar';
console.log(b.foo);
Hasilnya adalah "bar" yang ditampilkan dalam sebuah peringatan. Itu cukup adil, a
dan b
sebenarnya hanyalah alias untuk objek yang sama. Lalu saya berpikir, bagaimana saya bisa membuat contoh ini lebih sederhana.
a = b = 'foo';
a = 'bar';
console.log(b);
Itu kurang lebih sama, bukan? Nah kali ini, hasilnya foo
tidak bar
seperti yang saya harapkan dari perilaku contoh pertama.
Mengapa ini terjadi?
NB Contoh ini bisa lebih disederhanakan lagi dengan kode berikut:
a = {};
b = a;
a.foo = 'bar';
console.log(b.foo);
a = 'foo';
b = a;
a = 'bar';
console.log(b);
(Saya menduga bahwa JavaScript memperlakukan primitif seperti string dan integer secara berbeda dengan hash. Hash mengembalikan penunjuk sementara primitif "inti" mengembalikan salinan dirinya sendiri)
sumber
Jawaban:
Dalam contoh pertama, Anda menyetel properti dari objek yang sudah ada. Dalam contoh kedua, Anda menetapkan objek baru.
a
danb
sekarang penunjuk ke objek yang sama. Jadi, saat Anda melakukannya:Ini set
b.foo
juga sejaka
danb
menunjuk ke objek yang sama.Namun!
Jika Anda melakukan ini sebagai gantinya:
Anda mengatakan itu
a
menunjuk ke objek yang berbeda sekarang. Ini tidak berpengaruh pada apa yanga
disebutkan sebelumnya.Dalam JavaScript, menetapkan variabel dan menetapkan properti adalah 2 operasi berbeda. Yang terbaik adalah memikirkan variabel sebagai penunjuk ke objek, dan ketika Anda menetapkan langsung ke variabel, Anda tidak memodifikasi objek apa pun, hanya menunjuk variabel Anda ke objek yang berbeda.
Tapi menugaskan properti, seperti
a.foo
, akan mengubah objek yanga
dituju. Ini, tentu saja, juga mengubah semua referensi lain yang mengarah ke objek ini hanya karena semuanya menunjuk ke objek yang sama.sumber
var foo = new String('foo');
, maka itu akan menjadi objek string (dantypeof
akan mengkonfirmasi ini). Tetapi jika Anda mendeklarasikannya melalui string literal, maka mereka adalah string primitif. Lihat: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…Pertanyaan Anda telah dijawab dengan memuaskan oleh Squeegy - ini tidak ada hubungannya dengan objek vs. primitif, tetapi dengan penugasan ulang variabel vs. properti pengaturan dalam objek referensi yang sama.
Sepertinya ada banyak kebingungan tentang tipe JavaScript dalam jawaban dan komentar, jadi berikut adalah pengantar kecil untuk sistem tipe JavaScript:
Dalam JavaScript, ada dua jenis nilai yang berbeda secara fundamental: primitif dan objek (dan tidak ada yang namanya 'hash').
String, angka, dan boolean serta
null
danundefined
bersifat primitif, objek adalah segala sesuatu yang dapat memiliki properti. Bahkan array dan fungsi adalah objek biasa dan oleh karena itu dapat menampung properti arbitrer. Mereka hanya berbeda dalam properti [[Class]] internal (fungsi tambahan memiliki properti yang disebut [[Call]] dan [[Construct]], tapi hei, itu detailnya).Alasan nilai primitif dapat berperilaku seperti objek adalah karena autoboxing, tetapi primitif itu sendiri tidak dapat menyimpan properti apa pun.
Berikut ini contohnya:
Ini akan menampilkan
undefined
:a
memegang nilai primitif, yang dipromosikan menjadi objek saat menetapkan propertifoo
. Tetapi objek baru ini segera dibuang, sehingga nilainyafoo
hilang.Pikirkan seperti ini:
sumber
Anda kurang lebih benar kecuali bahwa yang Anda sebut sebagai "hash" sebenarnya hanyalah sintaks singkat untuk sebuah Objek.
Dalam contoh pertama, a dan b merujuk ke objek yang sama. Dalam contoh kedua, Anda mengubah a untuk merujuk ke sesuatu yang lain.
sumber
ini adalah versi saya dari jawabannya:
sumber
Anda menyetel a untuk menunjuk ke objek string baru, sementara b terus menunjuk ke objek string lama.
sumber
Dalam kasus pertama Anda mengubah beberapa properti objek yang terdapat dalam variabel, dalam kasus kedua Anda menetapkan nilai baru ke variabel. Itu adalah hal yang berbeda secara fundamental. Variabel
a
danb
entah bagaimana secara ajaib ditautkan oleh tugas pertama, mereka hanya berisi objek yang sama. Itu juga terjadi pada contoh kedua, sampai Anda menetapkan nilai baru keb
variabel.sumber
Perbedaannya adalah antara tipe dan objek sederhana.
Apa pun yang merupakan objek (seperti array atau fungsi) diteruskan dengan referensi.
Apa pun yang berjenis sederhana (seperti string atau angka) akan disalin.
Saya selalu memiliki fungsi copyArray yang berguna sehingga saya yakin saya tidak membuat banyak alias ke array yang sama.
sumber