En zarif şekilde bir JavaScript clone itiraz
Bir nesne var x
. Kopyalamak nesne y
değişiklikler x
değiştirme y
gibi istiyorum.
JavaScript ile bunu yapmanın en zarif yolu nedir?
Edit: kopyalama nesneleri yerleşik JavaScript nesneleri türetilen ek, istenmeyen özellikler neden olacağını fark ettim. Bu, edebi-inşa kendi nesnelerden birini taklit ediyorum, çünkü bu bir sorun değil.
CEVAP
JavaScript herhangi bir nesne için bunu yapmak için basit veya kolay olmayacak. Yanlışlıkla prototip ve yeni örnek kopyalanan değil bırakılmalıdır nesnenin prototip niteliklerini tespit edilen sorun haline çalışacaktır. Örneğin, bazı cevaplar tasvir gibi Object.prototype
clone
bir yöntem ekleyerek, açıkça bu öznitelik atlamak gerekir. Peki ya diğer ek yöntemler Object.prototype
veya diğer ara prototip eklenirse, biliyor musunuz? Bu durumda, hasOwnProperty
yöntemi ile, yerel olmayan beklenmedik niteliklerini tespit etmek gerekir, bu yüzden mi, gerekmez öznitelikleri kopyalamak.
Olmayan sayısız özelliklerinin yanı sıra, özellikleri gizli nesneleri kopyalamaya çalıştığınızda zor bir sorunla karşılaşırsınız. Örneğin, prototype
için fonksiyon gizli bir özellik. Ayrıca, bir nesnenin prototip niteliği ile de gizli, ve döngü için bir kaynak nesne nitelikleri üzerinden yineleme gönderilmez __proto__
başvurulan. __proto__
Firefox'un JavaScript yorumlayıcısı için özel olabilir ve bir şey diğer tarayıcılarda farklı olabilir, ama resmi olsun. Her şey sayısız. Eğer adını biliyorsanız gizli bir nitelik kopyalayabilirsiniz, ama bunu otomatik olarak keşfetmek için başka bir yol bilmiyorum.
Zarif bir çözüm arayışı içinde başka bir Budak prototip mirası doğru kurma sorunudur. Eğer kaynak nesne prototip Object
, o zaman sadece oluşturma Yeni bir genel nesne ile {}
işe yarar, ama eğer kaynak prototip bazı torunu Object
sonra çıkacak eksik ek üyelerden prototip olan atladın kullanarak hasOwnProperty
filtre veya ... ... prototip, ama sayısız değildi ilk başta. Bir çözüm kaynağı constructor
özellik ilk kopya nesne nesne ve öznitelikleri kopyalayın aramak için olabilir, ama yine de olmayan sayısız nitelikleri olsun. Örneğin, Date
bir nesne gizli bir üyesi olarak kendi veri depoları:
function clone(obj) {
if (null == obj || "object" != typeof obj) return obj;
var copy = obj.constructor();
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
}
return copy;
}
var d1 = new Date();
/* Wait for 5 seconds. */
var start = (new Date()).getTime();
while ((new Date()).getTime() - start < 5000);
var d2 = clone(d1);
alert("d1 = " d1.toString() "\nd2 = " d2.toString());
d1
tarih dizesi d2
bunun arkasında 5 saniye olacak. Date
başka bir yapmak için bir yol setTime
yöntemini çağırarak, ama bu Date
sınıf özgüdür. Yanılmaktan mutlu olurum ama bu sorun için kurşun geçirmez genel bir çözüm olduğunu sanmıyorum!
Ne zaman uygulamak için genel derin kopyalama sona erdi uzlaşarak farz ediyorum ki sadece kopyalamak gerekiyor bir düz Object
, Array
, Date
, String
, Number
, ya Boolean
. Son 3 tip değişmez, sığ bir kopyasını yapmak ve bunu dert değiştirme değil. Ben daha herhangi bir öğe Object
Array
içerdiği de bu listede 6 basit türlerinden biri olacağını düşünmüştüm. Bu kodu aşağıdaki gibi yapılabilir:
function clone(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] = clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
Yukarıdaki işlevi yeterince bahsettim 6 basit türleri için çalışmak sürece, nesneleri veri ve ağaç yapısı oluşturmak diziler. Bu nesne aynı veri için birden fazla başvuru yok. Örneğin:
// This would be cloneable:
var tree = {
"left" : { "left" : null, "right" : null, "data" : 3 },
"right" : null,
"data" : 8
};
// This would kind-of work, but you would get 2 copies of the
// inner node instead of 2 references to the same copy
var directedAcylicGraph = {
"left" : { "left" : null, "right" : null, "data" : 3 },
"data" : 8
};
directedAcyclicGraph["right"] = directedAcyclicGraph["left"];
// Cloning this would cause a stack overflow due to infinite recursion:
var cylicGraph = {
"left" : { "left" : null, "right" : null, "data" : 3 },
"data" : 8
};
cylicGraph["right"] = cylicGraph;
Herhangi bir JavaScript nesnesi işlemek için mümkün olmayacaktır, ama birçok amaç için yeterli sadece bir iş olacağını kabul etmediğin sürece bunu atmak herhangi bir şey için olabilir.
Nasıl verimli bir şekilde anahtarları/...
Daha iyi bir şekilde Javascript işlevi...
En zarif şekilde, string Python boş ol...
En verimli şekilde sıfır JavaScript di...
JavaScript algılama, boş zaman zarif...