2011-10-03 14 views
5

Zawsze zakładałem, że prototyp funkcji był wspólny dla wszystkich obiektów, w sensie odniesienia. Jeśli więc zmienisz wartość właściwości prototypu, wszystkie obiekty, które mają ten prototyp, również zmienią wartości dla nich. Na przykład poniżej wydaje się, że zamiast paska właściwości, który jest dzielony między wszystkie obiekty, jest on kopiowany. Czy to jest poprawne? Czy właściwości prototypu konstruktora są po prostu skopiowane do wszystkich obiektów klas, gdy są tworzone, lub czy są one wspólne dla powiązania?JavaScript i funkcja prototypowa przypisanie

function foo() 
{ 
    this.bar = 1; 
} 
function derived() { } 
derived.prototype = new foo() 

object1 = new derived() 
object2 = new derived() 

object1.bar = 2; 
//but notice if I had said here derived.prototype.bar = 3, object1.bar would still equal 2 but object2.bar would equal 3 
alert(object2.bar) // this prints 1; 

Odpowiedz

12

Po przypisaniu object1.bar = 2, tworzysz własność na object1, ten istnieje tylko w tej instancji obiektu, a to nie ma nic wspólnego z jego prototyp.

Ta nieruchomość na object1 będzie cieniu wartość jednego istniejącego na derived.prototype, oznacza to, że podczas odnośnika object1.bar będzie znaleźć wartość bezpośrednio istniejącego na tym obiekcie.

Z drugiej strony, jeśli odnośnika object2.bar, cel ten nie posiada własnego bar własność, więc wyszukiwanie nieruchomości będzie szukać na obiekt ten dziedziczy (derived.prototype) i będzie znaleźć wartość 1.

Twój obiekt struktura wygląda mniej więcej tak:

 
object1 
-------- 
| bar: 2 | ----------------- 
--------     |   derived.prototype 
          |  ---------- 
          |------> | bar: 1 | -- foo.prototype 
object2 (no own properties)|  ---------- | ------------------ 
--------     |      -> | constructor: foo | 
|  | -----------------       ------------------ 
--------             | 
                  v 
                ------------------ 
                | Object.prototype | 
                ------------------ 
                  | 
                  v 
                  null 

Jeżeli ---> linie oznaczają wewnętrzną [[Prototype]] link, który wyraża dziedziczenia.

+0

ohhh, ma sens, więc dopóki nie przypisuję go ponownie, odnosi się on do odziedziczonej własności, więc gdy ją przydzielę, stanie się ona własnością własną? – rubixibuc

+0

Mam to teraz, ten schemat bardzo pomógł, dziękuję bardzo, twoja odpowiedź była niesamowita :-) – rubixibuc

+0

@rubixibuc, w prawo, po przydzieleniu go, stanie się on własnością własna i będzie * cienia * dowolną wartość w górę w łańcuchu prototypów. Zwróć też uwagę, że nie można zmienić łącza '[[Prototyp]]' po utworzeniu obiektu, na przykład po utworzeniu obiektów 'object1' i' object2', możesz przypisać inny obiekt do 'derived.prototype', co nie wpłynie na właściwości dziedziczone przez te dwa obiekty. – CMS

2

Na przykład, masz kod:

function Animal() { 
} 
Animal.prototype.name="animal"; 

function Dog() { 
} 
Dog.prototype = new Animal 
Dog.prototype.constructor=Dog; 
Dog.prototype.name="dog"; 

object1 = new Animal(); 
object2 = new Dog(); 

W efekcie masz dwie instancje obiektu, który wyglądał jak (można to sprawdzić na przykład w Chrome DevTools lub FF Firebug lub ...):

object1: 
    __proto__: (is ref into an Animal.prototype object) 
    constructor: function Animal() 
    name: "animal" 
    __proto__: Object (is ref into an Object.prototype object) 

object2: 
    __proto__: (is ref into an Dog.prototype object) 
    constructor: function Dog() 
    name: "dog" 
    __proto__: (is ref into an Animal.prototype object) 
     constructor: function Animal() 
     name: "animal" 
     __proto__: (is ref into an Object.prototype object) 

Po uruchomieniu kolejnego kodu (przykładowo):

alert(object1.name); // displayed "animal" 
alert(object2.name); // displayed "dog" 

Co się stało? 1) JavaScript szukał nazwy właściwości w instancji obiektu (w object1 lub object2). 2) Gdy nie został znaleziony, wyszukał obiekt w instancji obiektu o właściwości: proto (to samo co prototyp funkcji klasy). 3) Gdy nie były wyświetlane, wyglądało na proto z proto i następną, gdy nie znaleziono, znaleziono właściwość i inne. Jeśli w wyniku wyszukiwania zostanie znaleziona właściwość, zwrócona zostanie wartość, jeśli nie zostanie znaleziona, zwrócona zostanie wartość undefined.

Co się stało, jeśli wykonać następny kod:

object2.name = "doggy"; 

W rezultacie masz na object2:

object2: 
    name: "doggy" 
    __proto__: (is ref into an Dog.prototype object) 
    constructor: function Dog() 
    name: "dog" 
    __proto__: (is ref into an Animal.prototype object) 
     constructor: function Animal() 
     name: "animal" 
     __proto__: (is ref into an Object.prototype object) 

nieruchomości jest przypisany bezpośrednio do instancji obiektu, ale prototyp obiektu pozostaje niezmieniona.I po wykonaniu:

alert(object1.name); // displayed "animal" 
alert(object2.name); // displayed "doggy" 

Kiedy trzeba utworzyć | zmiana wspólne właściwość klasy, można użyć jednego z najbliższych algoritms: 1)

Animal.prototype.secondName="aaa"; 
alert(object1.secondName); // displayed "aaa" 
alert(object2.secondName); // displayed "aaa" 
Animal.prototype.secondName="bbb"; 
alert(object1.secondName); // displayed "bbb" 
alert(object2.secondName); // displayed "bbb" 
// but 
Animal.prototype.secondName="ccc"; 
object1.secondName="ddd"; 
alert(object1.secondName); // displayed "ccc" 
alert(object2.secondName); // displayed "ddd" 

2) Utwórz właściwość typu object w prototypie klasy funkcji i przypisz wartości do właściwości tego obiektu.

Animal.prototype.propObject={thirdName:"zzz"}; 
alert(object1.propObject.thirdName); // displayed "zzz" 
alert(object2.propObject.thirdName); // displayed "zzz" 
Animal.prototype.propObject.thirdName="yyy"; 
alert(object1.propObject.thirdName); // displayed "yyy" 
alert(object2.propObject.thirdName); // displayed "yyy" 
object1.propObject.thirdName="xxx"; 
alert(object1.propObject.thirdName); // displayed "xxx" 
alert(object2.propObject.thirdName); // displayed "xxx" 
object2.propObject.thirdName="www"; 
alert(object1.propObject.thirdName); // displayed "www" 
alert(object2.propObject.thirdName); // displayed "www" 
+0

Nicely Explained. –