Temel fark, Nesnelerin yalnızca Haritalar'ın herhangi bir anahtar türünü az ya da çok desteklediği dize anahtarlarını desteklemesidir.
Ben yaparsanız obj[123] = true
o zaman ve Object.keys(obj)
o zaman alacak ["123"]
yerine [123]
. Bir Harita, anahtarın türünü ve [123]
büyük olan dönüşü koruyacaktır . Haritalar ayrıca Nesneleri anahtar olarak kullanmanızı sağlar. Geleneksel olarak bunu yapmak için nesnelere onları hash etmek için benzersiz bir tanımlayıcı vermelisiniz ( getObjectId
standardın bir parçası olarak JS'de hiç bir şey görmedim sanmıyorum ). Haritalar ayrıca siparişin korunmasını garanti eder, bu nedenle koruma için her şey daha iyi olur ve bazen birkaç çeşit yapmanız gerektiğini kaydedebilirsiniz.
Pratikte haritalar ve nesneler arasında çeşitli artılar ve eksiler vardır. Nesneler, JavaScript'in çekirdeğine çok sıkı bir şekilde entegre olmanın hem avantajlarını hem de dezavantajlarını kazanır ve bu da onları önemli destek farkının ötesinde önemli ölçüde Haritadan ayırır.
Acil bir avantaj, nesneler için sözdizimsel desteğe sahip olmanızdır. JSON ile de doğrudan destek alabilirsiniz. Karma olarak kullanıldığında, herhangi bir özelliği olmayan bir nesneyi elde etmek can sıkıcıdır. Varsayılan olarak Nesneleri bir karma tablosu olarak kullanmak istiyorsanız, bunlar kirlenir ve hasOwnProperty
özelliklere erişirken genellikle bunları çağırmanız gerekir. Burada varsayılan olarak Nesnelerin nasıl kirlendiğini ve karma olarak kullanılmak üzere umarım kirlenmemiş nesnelerin nasıl oluşturulacağını görebilirsiniz:
({}).toString
toString() { [native code] }
JSON.parse('{}').toString
toString() { [native code] }
(Object.create(null)).toString
undefined
JSON.parse('{}', (k,v) => (typeof v === 'object' && Object.setPrototypeOf(v, null) ,v)).toString
undefined
Nesneler üzerindeki kirlilik, yalnızca kodu daha can sıkıcı, daha yavaş, vb hale getiren bir şey değil, aynı zamanda güvenlik için potansiyel sonuçlara yol açabilir.
Nesneler saf karma tablolar değildir ancak daha fazlasını yapmaya çalışırlar. hasOwnProperty
Uzunluğunu kolayca elde edememek gibi baş ağrılarınız var ( Object.keys(obj).length
) vb. Nesnelerin yalnızca karma haritalar olarak değil, dinamik genişletilebilir Nesneler olarak kullanılması amaçlanmıştır ve bu yüzden onları saf karma tablolar olarak kullandığınızda sorunlar ortaya çıkar.
Karşılaştırma / Çeşitli genel işlemlerin listesi:
Object:
var o = {};
var o = Object.create(null);
o.key = 1;
o.key += 10;
for(let k in o) o[k]++;
var sum = 0;
for(let v of Object.values(m)) sum += v;
if('key' in o);
if(o.hasOwnProperty('key'));
delete(o.key);
Object.keys(o).length
Map:
var m = new Map();
m.set('key', 1);
m.set('key', m.get('key') + 10);
m.foreach((k, v) => m.set(k, m.get(k) + 1));
for(let k of m.keys()) m.set(k, m.get(k) + 1);
var sum = 0;
for(let v of m.values()) sum += v;
if(m.has('key'));
m.delete('key');
m.size();
Farklı inişler ve çıkışlar (performans, kısa, taşınabilir, uzatılabilir, vb.) İle birkaç seçenek, yaklaşım, yöntem, vb. Vardır. Nesneler, dilin çekirdeğini oluşturmak için biraz gariptir, bu nedenle onlarla çalışmak için birçok statik yönteminiz vardır.
Ayrıca, anahtar türlerini koruyan Haritalar'ın yanı sıra nesneler gibi şeyleri, nesnelerin sahip olduğu yan etkilerden izole edilmiş anahtarlar olarak destekleyebilmesinin yanı sıra. Bir Harita saf bir karmadır, aynı zamanda bir nesne olmaya çalışmak konusunda karışıklık yoktur. Haritalar, proxy işlevleriyle de kolayca genişletilebilir. Nesne şu anda bir Proxy sınıfına sahiptir, ancak performans ve bellek kullanımı çok zordur, aslında Nesneler için Harita'ya şu anda Proxy'den daha iyi performans gösteren kendi proxy'nizi oluşturmak.
Haritalar için önemli bir dezavantaj, bunların doğrudan JSON ile desteklenmemesidir. Ayrıştırma mümkündür, ancak birkaç videoyla sohbete sahiptir:
JSON.parse(str, (k,v) => {
if(typeof v !== 'object') return v;
let m = new Map();
for(k in v) m.set(k, v[k]);
return m;
});
Yukarıdakiler ciddi bir performans isabeti sunacak ve herhangi bir dize anahtarını desteklemeyecektir. JSON kodlaması daha da zor ve problemlidir (bu birçok yaklaşımdan biridir):
// An alternative to this it to use a replacer in JSON.stringify.
Map.prototype.toJSON = function() {
return JSON.stringify({
keys: Array.from(this.keys()),
values: Array.from(this.values())
});
};
Bu yalnızca Haritalar kullanıyorsanız o kadar da kötü değildir, ancak türleri karıştırırken veya skaler olmayan değerleri anahtar olarak kullanırken sorun yaşayacaktır (JSON, IE dairesel nesne başvurusu gibi bu tür bir sorunla mükemmel değildir). Ben test etmedim ama şansı stringize göre performansı ciddi zarar vardır.
Diğer komut dosyası dillerinde genellikle Harita, Nesne ve Dizi için açık skaler olmayan türler olduğu için sorun yoktur. Web geliştirme genellikle PHP için Array / Map nesnelerini özellikleri için A / M kullanarak ve JS Map / Object'i Array ile M / O genişleterek birleştirir. Karmaşık türleri birleştirmek, şeytanın yüksek seviyeli kodlama dillerinden oluşan çetesidir.
Şimdiye kadar bunlar büyük ölçüde uygulama ile ilgili konulardır, ancak temel operasyonlar için performans da önemlidir. Performans da karmaşıktır çünkü motora ve kullanıma bağlıdır. Herhangi bir hatayı ekleyemediğim için testlerimi bir tuz tanesi ile yap (bunu acele etmeliyim). Ayrıca benimkini sadece kaba bir endikasyon vermek için sadece çok spesifik basit senaryoları incelediği için onaylamanız gerekir. Chrome'da çok büyük nesneler / haritalar için yapılan testlere göre, silme nedeniyle nesnelerin performansı daha kötüdür; görünüşe göre O (1) yerine anahtar sayısıyla bir şekilde orantılıdır:
Object Set Took: 146
Object Update Took: 7
Object Get Took: 4
Object Delete Took: 8239
Map Set Took: 80
Map Update Took: 51
Map Get Took: 40
Map Delete Took: 2
Chrome'un alma ve güncelleme konusunda açıkça güçlü bir avantajı var, ancak silme performansı korkunç. Haritalar bu durumda az miktarda daha fazla bellek kullanır (havai), ancak yalnızca bir Nesne / Harita milyonlarca anahtarla test edildiğinde, haritalar için ek yükün etkisi iyi ifade edilmez. Bellek yönetimi ile nesneleri doğru bir şekilde okuyorsam, nesnelerin lehine bir fayda olabilir daha önce ücretsiz gibi görünüyor.
Bu belirli kıyaslama için Firefox'ta farklı bir hikaye:
Object Set Took: 435
Object Update Took: 126
Object Get Took: 50
Object Delete Took: 2
Map Set Took: 63
Map Update Took: 59
Map Get Took: 33
Map Delete Took: 1
Hemen bu özel ölçütte Firefox'taki nesnelerden silinmenin herhangi bir soruna neden olmadığını, ancak diğer ölçütlerde özellikle Chrome'da olduğu gibi birçok anahtar olduğunda sorunlara neden olduğunu belirtmeliyim. Haritalar, büyük koleksiyonlar için Firefox'ta açıkça üstündür.
Ancak bu hikayenin sonu değil, pek çok küçük nesne veya harita ne olacak? Bu hızlı bir kıyaslama yaptım ama kapsamlı bir (ayar / alma) değil yukarıdaki işlemleri az sayıda tuşları ile en iyi performans. Bu test daha çok bellek ve başlatma ile ilgilidir.
Map Create: 69 // new Map
Object Create: 34 // {}
Yine bu rakamlar farklılık gösterir, ancak temelde Object iyi bir ipucuna sahiptir. Bazı durumlarda, nesnelerin harita üzerindeki önceliği aşırıdır (~ 10 kat daha iyi), ancak ortalama 2-3 kat daha iyiydi. Aşırı performans artışları her iki yönde de işe yarayabilir. Bunu yalnızca Chrome'da ve profil kullanımı ve ek yükü oluşturmak için oluşturmada test ettim. Chrome'da, bir tuşa sahip Haritalar'ın bir tuşa sahip Nesneler'den yaklaşık 30 kat daha fazla bellek kullandığını görünce oldukça şaşırdım.
Yukarıdaki işlemlerin birçoğunu test etmek için (4 tuş):
Chrome Object Took: 61
Chrome Map Took: 67
Firefox Object Took: 54
Firefox Map Took: 139
Bellek tahsisi açısından, bunlar boşaltma / GC açısından aynı şekilde davrandılar, ancak Harita 5 kat daha fazla bellek kullandı. Bu testte 4 anahtar kullanıldı, burada son testte olduğu gibi sadece bir anahtar ayarladım, böylece bu bellek yükündeki azalmayı açıklayacaktı. Bu testi birkaç kez çalıştırdım ve Harita / Nesne, genel hız açısından Chrome için genel olarak az ya da çok boyun ve boyun. Küçük Nesneler için Firefox'ta, genel olarak haritalara göre kesin bir performans avantajı vardır.
Bu elbette çılgınca değişebilecek bireysel seçenekleri içermez. Bu rakamlarla mikro optimizasyon önermem. Bundan kurtulabileceğiniz şey, genel bir kural olarak, çok büyük anahtar / değer depoları için Haritalar'ı ve küçük anahtar / değer depoları için nesneleri daha güçlü bir şekilde ele almanızdır.
Bunun ötesinde bu iki ile en iyi strateji onu uygulamak ve sadece ilk işe yapmak. Profil oluştururken, nesne anahtar silme durumunda görülen motor tuhaflıkları nedeniyle onlara bakarken bazen yavaş olacağını düşünmediğiniz şeylerin inanılmaz derecede yavaş olabileceğini akılda tutmak önemlidir.