Memecahkan Masalah Khusus
Anda bisa menggunakan pernyataan tipe untuk memberi tahu kompiler bahwa Anda lebih tahu:
public clone(): any {
var cloneObj = new (this.constructor() as any);
for (var attribut in this) {
if (typeof this[attribut] === "object") {
cloneObj[attribut] = this[attribut].clone();
} else {
cloneObj[attribut] = this[attribut];
}
}
return cloneObj;
}
Kloning
Ingatlah bahwa kadang-kadang lebih baik menulis pemetaan Anda sendiri - daripada menjadi benar-benar dinamis. Namun, ada beberapa trik "kloning" yang dapat Anda gunakan yang memberi Anda efek perbedaan.
Saya akan menggunakan kode berikut untuk semua contoh berikut:
class Example {
constructor(public type: string) {
}
}
class Customer {
constructor(public name: string, public example: Example) {
}
greet() {
return 'Hello ' + this.name;
}
}
var customer = new Customer('David', new Example('DavidType'));
Opsi 1: Sebarkan
Properti: Ya
Metode: Tidak
Salin Jauh: Tidak
var clone = { ...customer };
alert(clone.name + ' ' + clone.example.type); // David DavidType
//alert(clone.greet()); // Not OK
clone.name = 'Steve';
clone.example.type = 'SteveType';
alert(customer.name + ' ' + customer.example.type); // David SteveType
Opsi 2: Object.assign
Properti: Ya
Metode: Tidak
Salin Jauh: Tidak
var clone = Object.assign({}, customer);
alert(clone.name + ' ' + clone.example.type); // David DavidType
alert(clone.greet()); // Not OK, although compiler won't spot it
clone.name = 'Steve';
clone.example.type = 'SteveType';
alert(customer.name + ' ' + customer.example.type); // David SteveType
Opsi 3: Object.create
Properti:
Metode Warisan
:
Salinan Jauh Warisan : Warisan Dangkal (perubahan mendalam memengaruhi dokumen asli dan klon)
var clone = Object.create(customer);
alert(clone.name + ' ' + clone.example.type); // David DavidType
alert(clone.greet()); // OK
customer.name = 'Misha';
customer.example = new Example("MishaType");
// clone sees changes to original
alert(clone.name + ' ' + clone.example.type); // Misha MishaType
clone.name = 'Steve';
clone.example.type = 'SteveType';
// original sees changes to clone
alert(customer.name + ' ' + customer.example.type); // Misha SteveType
Opsi 4: Fungsi Salin Jauh
Properti: Ya
Metode: Tidak
Salin Jauh: Ya
function deepCopy(obj) {
var copy;
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = deepCopy(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = deepCopy(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
var clone = deepCopy(customer) as Customer;
alert(clone.name + ' ' + clone.example.type); // David DavidType
// alert(clone.greet()); // Not OK - not really a customer
clone.name = 'Steve';
clone.example.type = 'SteveType';
alert(customer.name + ' ' + customer.example.type); // David DavidType
cloned instanceof MyClass === true
?1.Gunakan operator spread
Operator spread mengambil semua bidang dari obj1 dan menyebarkannya di obj2. Dalam hasilnya Anda mendapatkan objek baru dengan referensi baru dan bidang yang sama dengan yang asli.
Ingat bahwa itu adalah salinan dangkal, itu berarti bahwa jika objek bersarang maka params komposit bersarangnya akan ada di objek baru dengan referensi yang sama.
2.Object.assign ()
Object.assign membuat salinan nyata, tetapi hanya memiliki properti sendiri, sehingga properti dalam prototipe tidak akan ada di objek yang disalin. Ini juga merupakan salinan dangkal.
3.Object.create ()
Object.create
tidak melakukan kloning nyata , itu menciptakan objek dari prototipe. Jadi gunakan itu jika objek harus mengkloning properti tipe primer, karena penugasan properti tipe primer tidak dilakukan oleh referensi.Plus dari Object.create adalah bahwa fungsi apa pun yang dinyatakan dalam prototipe akan tersedia di objek kami yang baru dibuat.
Beberapa hal tentang salinan dangkal
Salinan dangkal menempatkan objek baru ke semua bidang yang lama, tetapi itu juga berarti bahwa jika objek asli memiliki bidang tipe komposit (objek, array, dll.) Maka bidang tersebut dimasukkan ke objek baru dengan referensi yang sama. Mutasi bidang tersebut dalam objek asli akan tercermin dalam objek baru.
Mungkin terlihat seperti jebakan, tetapi benar-benar situasi ketika seluruh objek kompleks perlu disalin jarang terjadi. Salinan dangkal akan menggunakan kembali sebagian besar memori yang berarti sangat murah dibandingkan dengan salinan dalam.
Salinan dalam
Operator spread dapat berguna untuk salinan dalam.
Kode di atas membuat salinan obj1 yang dalam. "Komposit" bidang komposit juga disalin ke obj2. Bidang mutasi "kompleks" tidak akan mencerminkan salinan.
sumber
Object.create(obj1)
menciptakan objek baru dan menetapkan objek sebagai prototipe. Tak satu pun bidang di obj1 yang disalin atau dikloning. Jadi perubahan pada obj1 tanpa memodifikasi obj2 akan terlihat, karena pada dasarnya tidak memiliki properti. Jika Anda memodifikasi objek2 terlebih dahulu, prototipe tidak akan terlihat untuk bidang yang Anda tentukan karena bidang objek2 dengan nama lebih dekat dalam hierarki.let b = Object.assign({}, a);
Coba ini:
Ini adalah solusi yang baik sampai Anda menggunakan objek yang sangat besar atau objek Anda memiliki sifat yang tidak dapat diubah.
Untuk menjaga keamanan jenis, Anda dapat menggunakan fungsi penyalinan di kelas tempat Anda ingin membuat salinan:
atau dengan cara statis:
sumber
undefined
Setidaknya dapat menyebabkan kunci yang hilang dengan nilai. jikaobjectToCopy = { x : undefined};
kemudian setelah menjalankan kode AndaObject.keys(objectToCopy).length
adalah1
, sementaraObject.keys(copy).length
ini0
.TypeScript / JavaScript memiliki operator sendiri untuk kloning dangkal:
sumber
Sangat mudah untuk mendapatkan salinan yang dangkal dengan "Object Spread" yang diperkenalkan di TypeScript 2.1
TypeScript ini:
let copy = { ...original };
menghasilkan JavaScript ini:
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html
sumber
Untuk klon dalam yang dapat disambungkan, dengan Jenis Informasi adalah,
sumber
JSON.stringify
clone
. :)undefined
nilai. Lihat komentar saya pada jawaban yang sama di atas: stackoverflow.com/questions/28150967/typescript-cloning-object/…Pandangan saya:
Object.assign(...)
hanya menyalin properti dan kami kehilangan prototipe dan metode.Object.create(...)
tidak menyalin properti untuk saya dan hanya membuat prototipe.Apa yang berhasil bagi saya adalah membuat prototipe menggunakan
Object.create(...)
dan menyalin properti menggunakan ituObject.assign(...)
:Jadi untuk objek
foo
, buat klon seperti ini:sumber
foo
menjadi orang tua prototipikal dariclonedFoo
(objek baru). Meskipun ini mungkin terdengar ok, Anda harus ingat bahwa properti yang hilang akan dicari dalam rantai prototipe, jadiconst a = { x: 8 }; const c = Object.assign(Object.create(a), a); delete c.x; console.log(c.x);
cetaklah 8, sementara seharusnyaundefined
! (Tautan REPL: repl.it/repls/CompetitivePreemptiveKeygen )foo
, properti itu akan muncul secara otomatis untukclonedFoo
! mis.foo.y = 9; console.log(clonedFoo.y)
akan mencetak9
bukanundefined
. Sangat mungkin bukan itu yang Anda minta!Anda juga dapat memiliki sesuatu seperti ini:
Pastikan Anda mengganti
clone
metode di semuaEntity
subclass jika tidak, Anda akan berakhir dengan klon parsial.Jenis pengembalian
this
akan selalu cocok dengan jenis instance.sumber
Tambahkan
"lodash.clonedeep": "^4.5.0"
kepackage.json
. Kemudian gunakan seperti ini:sumber
Jika Anda mendapatkan kesalahan ini:
Ini skrip yang benar:
sumber
cloneObj[attribut] = this.clone();
? atau maksud AndacloneObj[attribut] = this[attribut].clone();
Datang di masalah ini sendiri dan pada akhirnya menulis perpustakaan kecil cloneable-ts yang menyediakan kelas abstrak, yang menambahkan metode klon ke kelas mana pun memperluasnya. Kelas abstrak meminjam Fungsi Salin Jauh yang dijelaskan dalam jawaban yang diterima oleh Fenton hanya menggantikan
copy = {};
dengancopy = Object.create(originalObj)
untuk mempertahankan kelas objek asli. Berikut ini adalah contoh penggunaan kelas.Atau Anda bisa menggunakan
Cloneable.clone
metode pembantu:sumber
Ini tumbuk saya! Dan di sini ada tautan StackBlitz . Saat ini terbatas hanya menyalin tipe dan tipe objek sederhana tetapi dapat dimodifikasi dengan mudah saya pikir.
sumber
typeof null
juga merupakan objek, jadi kueri seharusnyaif (source[P] !== null && typeof source[P] === 'object')
. Jika tidak, nilai nol Anda akan berubah menjadi objek kosong.Karena TypeScript 3.7 dirilis, alias tipe rekursif sekarang didukung dan memungkinkan kita untuk mendefinisikan
deepCopy()
fungsi tipe aman :Tempat bermain
sumber
Untuk klon sederhana dari konten objek lubang, saya cukup merinci dan menguraikan contoh:
Sedangkan saya mengubah data di pohon objectToClone, tidak ada perubahan dalam cloneObject. Itu adalah permintaan saya.
Semoga ini bisa membantu
sumber
undefined
nilai. Lihat komentar saya pada jawaban yang sama di atas: stackoverflow.com/questions/28150967/typescript-cloning-object/…Saya akhirnya melakukan:
Karena:
dari @Fenton memberikan kesalahan runtime.
Versi naskah: 2.4.2
sumber
Bagaimana dengan jQuery lama yang bagus ?! Ini klon yang dalam:
sumber
Saya mencoba membuat layanan copy / klon generik yang mempertahankan tipe untuk objek bersarang. Senang umpan balik jika saya melakukan sesuatu yang salah, tetapi tampaknya berfungsi sejauh ini ...
sumber
Dalam typeScript saya uji dengan sudut, dan itu baik-baik saja
sumber
Untuk kloning mendalam suatu objek yang dapat berisi objek lain, array dan sebagainya saya gunakan:
Menggunakan:
sumber
Anda bisa menggunakan tugas penataan dengan sintaks spread :
sumber
Jika Anda sudah memiliki objek target, jadi Anda tidak ingin membuatnya lagi (seperti jika memperbarui array) Anda harus menyalin properti.
Jika telah melakukannya dengan cara ini:
Pujian sudah jatuh tempo. (lihat judul "versi 2")
sumber