Saat mengirimkan objek sebagai parameter, JavaScript meneruskannya dengan referensi dan mempersulit pembuatan salinan lokal objek.
var o = {}; (function(x){ var obj = x; obj.foo = 'foo'; obj.bar = 'bar'; })(o)
o
akan memiliki.foo
dan.bar
.Ini mungkin untuk menyiasatinya dengan kloning; contoh sederhana:
var o = {}; function Clone(x) { for(p in x) this[p] = (typeof(x[p]) == 'object')? new Clone(x[p]) : x[p]; } (function(x){ var obj = new Clone(x); obj.foo = 'foo'; obj.bar = 'bar'; })(o)
o
tidak akan memiliki.foo
atau.bar
.
Pertanyaan
- Apakah ada cara yang lebih baik untuk melewatkan objek berdasarkan nilai, selain membuat salinan / klon lokal?
javascript
vol7ron
sumber
sumber
Jawaban:
Tidak juga.
Bergantung pada apa yang sebenarnya Anda butuhkan, satu kemungkinan mungkin ditetapkan
o
sebagai prototipe objek baru.Jadi properti apa pun yang Anda tambahkan
obj
tidak akan ditambahkano
. Setiap properti yang ditambahkan keobj
dengan nama properti yang sama dengan properti dio
akan membayangio
properti.Tentu saja, setiap properti yang ditambahkan ke
o
akan tersediaobj
jika tidak dibayangi, dan semua objek yang adao
di rantai prototipe akan melihat pembaruan yang sama untuko
.Selain itu, jika
obj
memiliki properti yang mereferensikan objek lain, seperti Array, Anda harus memastikan untuk membayangi objek tersebut sebelum menambahkan anggota ke objek, jika tidak, anggota tersebut akan ditambahkanobj
, dan akan dibagikan di antara semua objek yang milikiobj
dalam rantai prototipe.Di sini Anda dapat melihat bahwa karena Anda tidak bayangan Array di
baz
ataso
denganbaz
properti padaobj
, yango.baz
Array akan diubah.Jadi, Anda harus membayangi terlebih dahulu:
sumber
Object.create
dalam jawaban saya, tetapi saya tidak ingin menjelaskan secara berlebihan tentang kedangkalan salinan ;-)var obj = new Object(x)
. Bagi saya, saya akan berpikir itunew Object(x)
akan tampilObject.create(x)
secara default - menariknew Object(x)
hanya meludahkan objek yang sama (seperti yang mungkin Anda perhatikan) . Alangkah baiknya jika ada cara asli untuk mengkloning. Tidak yakin apakah ada sesuatu yang sedang dikerjakan.Lihat jawaban ini https://stackoverflow.com/a/5344074/746491 .
Singkatnya,
JSON.parse(JSON.stringify(obj))
ini adalah cara cepat untuk menyalin objek Anda, jika objek Anda dapat diserialkan ke json.sumber
JSON
Tidak disertakan dan perlu didefinisikan - mungkin juga lebih deskriptif dengan nama sepertiClone
. Namun, saya curiga pendapat saya dapat berubah di masa depan, karena JSON lebih terintegrasi ke dalam perangkat lunak berbasis non-browser seperti database dan IDEBerikut adalah fungsi clone yang akan melakukan deep copy objek:
Sekarang Anda bisa menggunakan seperti ini:
sumber
Menggunakan
Object.assign()
Contoh:
Contoh lebih bersih yang melakukan hal yang sama:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
sumber
var b = Object.assign({}, a);
a
akan disalin sebagai referensi.Anda sedikit bingung tentang cara kerja objek di JavaScript. Referensi objek adalah nilai variabel. Tidak ada nilai unserialized. Saat Anda membuat objek, strukturnya disimpan dalam memori dan variabel yang ditetapkan untuk menyimpan referensi ke struktur itu.
Bahkan jika apa yang Anda tanyakan diberikan dengan cara yang mudah, konstruksi bahasa asli secara teknis masih merupakan kloning.
JavaScript benar-benar hanya nilai lewat ... hanya saja nilai yang diteruskan mungkin merujuk pada sesuatu.
sumber
Gunakan ini
x
danx1
akan menjadi dua objek yang berbeda, perubahanx
tidak akan berubahx1
sumber
Javascript selalu melewati nilai. Dalam hal ini, ia meneruskan salinan referensi
o
ke fungsi anonim. Kode menggunakan salinan referensi tetapi mengubah satu objek. Tidak ada cara untuk membuat javascript melewati apapun selain nilai.Dalam hal ini, yang Anda inginkan adalah meneruskan salinan objek yang mendasarinya. Mengkloning objek adalah satu-satunya jalan keluar. Metode klon Anda membutuhkan sedikit pembaruan
sumber
Sebagai pertimbangan bagi pengguna jQuery, ada juga cara untuk melakukannya dengan cara sederhana menggunakan kerangka kerja. Cara lain jQuery membuat hidup kita sedikit lebih mudah.
referensi :
sumber
Sebenarnya, Javascript selalu melewati nilai . Tetapi karena referensi objek adalah nilai , objek akan berperilaku seperti diteruskan oleh referensi .
Jadi untuk berjalan di sekitar ini, string objek dan parsing kembali, keduanya menggunakan JSON. Lihat contoh kode di bawah ini:
sumber
use obj2 = {... obj1} Sekarang kedua objek memiliki nilai yang sama dengan referensi yang berbeda
sumber
let a = {value: "old"}
let b = [...a]
b.value = "new"
, dan a akan{value: "old"}
, b akan{value: "new"}
. Tapi tidak berhasil kapanlet a = [{value: "old"}]
let b = [...a]
b[0].value = "new"
, dan a akan[{value: "new"}]
, b akan[{value: "new"}]
.Saya perlu menyalin objek berdasarkan nilai (bukan referensi) dan menurut saya halaman ini berguna:
Apa cara paling efisien untuk mengkloning objek dalam JavaScript? . Secara khusus, mengkloning objek dengan kode berikut oleh John Resig:
sumber
Dengan sintaks ES6:
let obj = Object.assign({}, o);
sumber
Object.assign
adalah tidak melakukan deep copy.Ketika Anda menyimpulkannya, itu hanya proxy yang terlalu rumit, tapi mungkin Catch-All Proxies bisa melakukannya?
sumber
Jika Anda menggunakan lodash atau
npm
, gunakan fungsi gabungan lodash untuk menyalin semua properti objek ke objek kosong baru seperti:var objectCopy = lodash.merge({}, originalObject);
https://lodash.com/docs#merge
https://www.npmjs.com/package/lodash.merge
sumber