Object.create (null) ile JS nesnesi mi oluşturuluyor?


150

JS nesneleri oluşturmanın pek çok yolunu biliyorum ama Object.create(null)bir tanesini bilmiyordum .

Soru:

tam olarak aynı mıdır:

var p = {}

vs

var p2 = Object.create(null);

?

Yanıtlar:


199

Eşdeğer değiller. {}.constructor.prototype == Object.prototypeancak Object.create(null)hiçbir şeyden miras kalmaz ve dolayısıyla hiçbir özelliği yoktur.

Başka bir deyişle: varsayılan olarak Nesne A JavaScript nesne devralır açıkça gibi onun prototip olarak null oluşturun sürece: Object.create(null).

{}bunun yerine Object.create(Object.prototype).


Chrome Devtool'da Object.create(null)bunun hiçbir __proto__özelliği olmadığını görebilirsiniz {}.

resim açıklamasını buraya girin


99

Kesinlikle eşdeğer değiller. Neden bir fark yarattığını daha iyi açıklamak için bu cevabı yazıyorum.

  1. var p = {};

    Özelliklerini ve yöntemlerini devralan bir nesne oluşturur Object.

  2. var p2 = Object.create(null);

    Hiçbir şeyi devralmayan bir nesne oluşturur.

Bir nesneyi harita olarak kullanıyorsanız ve yukarıdaki yöntem 1'i kullanarak bir nesne oluşturuyorsanız, haritada arama yaparken çok dikkatli olmanız gerekir. Özellikleri ve yöntemleri Objectdevralındığından, kodunuz, haritaya hiç eklemediğiniz anahtarların bulunduğu bir durumda çalıştırılabilir. Örneğin, bir arama yaptıysanız toString, bu değeri asla oraya koymasanız bile bir işlev bulacaksınız. Bunun gibi çalışabilirsiniz:

if (Object.prototype.hasOwnProperty.call(p, 'toString')) {
    // we actually inserted a 'toString' key into p
}

Bir şey atamanın iyi olduğuna dikkat edin, p.toStringdevralınan toStringişlevi geçersiz kılar p.

Sadece p.hasOwnProperty('toString')içine bir anahtar "hasOwnProperty" eklemiş olabileceğiniz için yapamayacağınızı unutmayın p, bu yüzden onu uygulamayı kullanmaya zorlarız Object.

Öte yandan, yukarıdaki yöntem 2'yi kullanırsanız, nesnelerin Objectharitada görünmesi konusunda endişelenmenize gerek kalmaz .

Bunun ifgibi basit bir mülkün varlığını kontrol edemezsiniz :

// Unreliable:
if (p[someKey]) {
    // ...
}

Değer boş bir dize olabilir false, veya null, veya undefined, veya 0, veya NaNvb. Olabilir. Bir özelliğin var olup olmadığını kontrol etmek için yine de kullanmanız gerekir Object.prototype.hasOwnProperty.call(p, someKey).


6
Bir mülkün varlığını kontrol etmek için daha basit bir alternatif:if (someKey in p) {
mrcrowl

2
@mrcrowl Yalnızca kullanıldıysa Object.create(null). Kesinlikle kullandığınız doğru olsa bile Object.create(null), kod değişebilir, nesne bir Objectnoktada miras bir ile değiştirilebilir gibi varsayımlar yapmamayı tercih ederim . hasOwnPropertyher zaman çalışır.
doug65536

1
Böyle bir şeye dikkat etmenin gereksiz olması gerektiğini hissediyorum. Cevabınızı takdir ediyorum, ancak belgeler hangi kodla çalışıyorsanız çalışmanız için gereken API'yi vermelidir. Github'dan rastgele bir kod alıyorsanız, çatallayabilir ve daha az belgelenmiş güncellemelerden koruyabilirsiniz. Bahsetmemek {}çok daha yaygındır Object.create(null), eğer kodunuz yanlışlıkla bu noktada devralınmış bir mülk kaparsa, muhtemelen endişelenmeniz gereken daha büyük hatalara sahip olursunuz. Yalnızca küçük bir optimizasyon olarak Object.create (null) kullanan kişileri görebiliyorum.
aaaaaa

Çift olumsuzlama !!p[key]ile iyi çalışır Object.create(null). Ama hasKey = (key, input) => Object.prototype.hasOwnProperty.call(input, key)kötü de değil
andreid

> P'ye sadece "hasOwnProperty" anahtarını eklediğiniz için p.hasOwnProperty ('toString') yapamayacağınızı unutmayın, bu yüzden onu Object içindeki uygulamayı kullanmaya zorlarız. Bu gereksiz. Bu durumda, herhangi bir yöntemi kullanamazsınız pçünkü her yöntem eklenebilir ve böylece güvenli olmaz.
xianshenglu

1

Nesneleri kullanarak {}oluşturmak, prototipi Object.prototypetemel işlevleri Objectprototipten devralan bir nesne yaratırken, nesneleri Object.create(null)oluştururken prototipi null olan boş bir nesne oluşturur.


0

Birisi uygulamak Object.create(null)istiyorsa, sadece nasıl çalıştığını bilmek. __proto__Standart olmayan kullanarak yazılmıştır ve bu nedenle tavsiye etmiyorum .

function objectCreateMimic()
{
  /*optional parameters: prototype_object, own_properties*/
  var P = arguments.length>0?arguments[0]:-1;
  var Q = arguments.length>1?arguments[1]:null;
  var o = {};
  if(P!==null && typeof P === "object")
  {
    o.__proto__ = P;
  }
  else if(P===null)
  {
    o.__proto__ = null;
  }
  if(Q!==null && typeof Q === "object")
  {
   for(var key in Q)
   {
     o[key] = Q[key];
   }
  }
  return o;
}

Not : Bunu meraktan yazdım ve sadece basit terimlerle yazılmış, örneğin, özellik tanımlayıcılarını ikinci nesneden dönüş nesnesine aktarmıyorum.


1
ECMAScript'in yaz aylarında piyasaya sürülmesinden itibaren __proto__artık resmi olarak dilin bir parçası olacağını unutmayın .
Chiru

1
Neden -1içinde arguments.length>0?arguments[0]:-1;?
happy_marmoset

@happy_marmoset geç yanıt, ancak Objectilk argüman verilmezse prototipin korunması için yalnızca boş olmayan bir yer tutucu gibi görünüyor . Değişken isimleri burada çok daha iyi olabilir.
Mike Hill

Ayrıca, ikinci parametre , gerçek özelliklerin kendisinden ziyade özellik tanımlayıcılarını tanımlamalıdır . Buradaki referansa bakın: developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Mike Hill

0

Object.create (null) ile bir Nesne oluşturduğunuzda, prototipsiz bir Nesne oluşturduğunuz anlamına gelir. null burada prototip zincirinin sonu anlamına gelir. Yine de {} gibi bir nesne oluşturduğunuzda Object prototype eklenecektir. Dolayısıyla bunlar biri prototip ve diğeri prototipsiz olmak üzere iki farklı nesnedir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.