2011-07-19 32 views
37

Muhtemelen prototip zincirinin yanında duran JavaScript'in en az anlaşılan kısmı.Yeni operatör nasıl çalışır?

Yani soru şu: nasıl yaptığını ...

new dataObj(args); 

... aslında bir nesne oluşturmak ve tanımlamak onun prototip zinciri/kurucular/vs?

Bu anahtar kelimeyi tam olarak anlamak için en iyisi bir alternatif göstermektir.

+2

Türü: http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript – Ivan

cevap

45

new operatör iç [[Construct]] yöntemini kullanır ve bu temelde şunları yapar: Bu durumda, new C böyle simüle edilebilir

  • ayarlar yeni bir yerel nesneyi başlatır Bu nesnenin iç [[Prototype]], İşlev prototype özelliğine işaret eder.
    • işlevin prototype özelliği bir amacı, Object.prototype yerine kullanılır (örneğin, bir sayı, String, Boolean, Tanımsız veya boş olarak ilkel değerleri) değilse.
  • nesnesi oluşturduktan sonra, kendi this değeri olarak nesnesi temin etmek; işlevini çağırır.
  • Çağrılan işlevin dönüş değeri ilkel ise, dahili olarak oluşturulan nesne döndürülür.
  • Aksi takdirde, bir nesne döndürülürse, dahili olarak oluşturulan nesne kaybolur.

new operatörün bu gibi ifade edilebilir etmez ne eşdeğer bir uygulama (ECMAScript 5 Object.create yöntem mevcut olduğu varsayılarak): İlgili arasında

function NEW(f) { 
    var obj, ret, proto; 

    // Check if `f.prototype` is an object, not a primitive 
    proto = Object(f.prototype) === f.prototype ? f.prototype : Object.prototype; 

    // Create an object that inherits from `proto` 
    obj = Object.create(proto); 

    // Apply the function setting `obj` as the `this` value 
    ret = f.apply(obj, Array.prototype.slice.call(arguments, 1)); 

    if (Object(ret) === ret) { // the result is an object? 
    return ret; 
    } 
    return obj; 
} 

// Example usage: 
function Foo (arg) { 
    this.prop = arg; 
} 
Foo.prototype.inherited = 'baz'; 

var obj = NEW(Foo, 'bar'); 
obj.prop;   // 'bar' 
obj.inherited;  // 'baz' 
obj instanceof Foo // true 
+0

Object.create (proto) ile değiştirilmekte güvenli olmalı> var newObj = {}; newObj.prototype = proto; ? – PicoCreator

+4

@ pico.creator: Hayır, 'prototype' özelliği yalnızca Kurucu olarak kullanıldığında İşlev nesneleri için anlamlıdır ve benim örneğimde 'yeni' uygulamasında bir kurucu kullanmak 'yeni' operatörünü kullanmak için gerekliydi. .. Diğer tek yolu, '__proto__' özelliğini kullanmak olurdu, ancak standart dışı ve kullanımdan kaldırılıyor. İşlev nesnelerinin prototipinin özelliği ile * iç * [[Prototip]] 'özelliği arasındaki farkı açıkladığım [bu yanıt] 'a bakın (http://stackoverflow.com/questions/2111288/#2111353). tüm nesneler prototip zincirini oluşturuyor. – CMS

+0

Terimin ikili kullanımı kesinlikle kafa karıştırıcı. Ancak cevap, nesne kurucu ayarını bıraktı; Benim deneyimlerimden dolayı, yapıcı işlevi klonlanmış, uygulanmış ve sonuçta .constructor değerine eklenmiş gibi görünüyor. – PicoCreator

8

ifadesi new C(arg1, arg2):

varsayarsak C bir JavaScript işlevi (aksi takdirde hata iletisi) 'dir:

  1. yeni bir boş nesne (hayır özellikleri)
  2. yeni prototipini ayarlar oluşturur C'un "prototype" özelliğinin değerine nesne.
    • Not: Bir işlev için prototype varsayılan değeri Object.prototype ayarlı prototip ve işlev C geri işaret eden bir constructor özelliğiyle (işlev ilan edildiğinde otomatik olarak oluşturulan) bir nesnedir.
    • Not: Terminoloji kafa karıştırıcı olabilir. "Prototip" adlı özellik, nesnenin prototipi ile aynı değil 'dır. Yalnızca işlevlerin "prototip" adlı özelliğe sahip olması, ancak tüm nesnelerin bir prototipi vardır.
  3. 'this', yeni nesneye ayarlanmış ve verilen argümanlarla işlevini C çağırır.
  4. C işlevini çağırıyorsanız, bir nesne döndürür, bu nesne ifadenin sonucudur. Aksi takdirde yeni oluşturulan nesne ifadenin sonucudur.

ECMAScript 5'te new seçeneğine alternatif olarak, yerleşik Object.createObject yöntemini kullanmak olacaktır.

var obj = Object.createObject(C.prototype); 
C.apply(obj, [arg1, arg2]); 

Standart JavaScript böylece Object.createObject dilin kendisi hayata olamaz, açıkça bir nesnenin prototip ayarlamak için izin vermez:

new C(arg1, arg2)

eşdeğer olacaktır. Bazı uygulamalar, standart olmayan özellik __proto__ üzerinden izin verir.

var obj = {}; 
obj.__proto__ = C.prototype; 
C.apply(obj, [arg1, arg2]); 
+1

# 2 noktasında not: Herhangi bir kullanıcı tanımlı fonksiyonun 'prototype' özelliğinin varsayılan değeri, 'yapıcı' içeren bir nesnedir. İşlev kendisine geri başvurur ve Object.prototype'dan miras alır. Bu nesne [işlev nesneleri oluşturulduğunda] başlatılır (http://es5.github.com/#x13.2). Object.create' hakkında, sadece [* [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [[] [] [] [] [] [] [] [] [] [] [] [] (http://stackoverflow.com/questions/3830800#3844768). Şerefe. – CMS