2010-01-21 24 views
7

o.prototype = {...} działa tylko wtedy, gdy o jest funkcją. Załóżmy mam następujący kodJavaScript prototyp ograniczony do funkcji?

conf = { 
    a: 2, 
    b: 4 
}; 
conf.prototype = { 
    d: 16 
} 

conf.a i conf.b jest OK i zwraca odpowiednie wartości. Ale conf.d nie zwraca 16 raczej nie jest zdefiniowane. Czy istnieje jakieś rozwiązanie, które powoduje, że generowanie oparte na prototypach może być również zastosowane do tego typu obiektów.

Odpowiedz

21

Mylisz właściwość prototype które mogą być wykorzystane na Constructor Functions i wewnętrzną[[Prototype]] własność .

Wszystkie obiekty mają tę wewnętrzną właściwość [[Prototype]] i tylko operator new podczas wywoływania jej za pomocą funkcji konstruktora może ją ustawić (poprzez wewnętrzną operację [[Construct]]).

Jeśli chcesz mieć prototypal dziedziczenie z instancji obiektów (bez użycia konstruktorów), Object.create technice Crockforda jest to, co chcesz (ta metoda jest obecnie częścią niedawno zatwierdzonym ECMAScript 5th Edition):

// Check if native implementation available 
if (typeof Object.create !== 'function') { 
    Object.create = function (o) { 
    function F() {} // empty constructor 
    F.prototype = o; // set base object as prototype 
    return new F(); // return empty object with right [[Prototype]] 
    }; 
} 

var confProto = { 
    d: 16 
}; 
var conf = Object.create(confProto); 
conf.a = 2; 
conf.b = 4; 

w powyższym kodzie conf będzie miała trzech członków, ale tylko a i b wola istnieje fizycznie na nim:

conf.hasOwnProperty('a'); // true 
conf.hasOwnProperty('b'); // true 
conf.hasOwnProperty('d'); // false 

Ponieważ d istnieje na conf [[Prototype]] (confProto).

property accessors, . i [] są odpowiedzialni rozwiązać właściwości patrząc w górę, jeśli to konieczne w łańcuchu prototypów (poprzez metody wewnętrznej [[Get]]).

+3

Czy osoba dokonująca wstrząsu może dodać komentarz? Zawsze staram się poprawić moje odpowiedzi :) – CMS

6

w JavaScript Są faktycznie dwa różnego rodzaju „prototyp”:

  1. Jednym z nich jest „ukryty” link każdy obiekt ma (użyjmy [[Prototype]] reprezentować ten ukryty odnośnik). literały obiektowe domyślnie mają swoje ukryte odnośniki wskazujące na Object.prototype, obiekty funkcji mają ukryty odnośnik wskazujący na Function.prototype, a tablice wskazują na Array.prototype. Te ukryte prototypowe łącza nie są powiązane z właściwościami o nazwie "prototyp". Nie możesz zmienić tych ukrytych linków, dodając lub modyfikując o.prototype.
  2. Po drugie, wszystkie obiekty funkcji mają automatycznie specjalną właściwość o nazwie "prototype". Dotyczy to głównie użycia wzorca wywołania konstruktora.

[[Prototype]] jest używany do poszukiwania właściwości (np rodzica w klasycznych hierarchii), gdy własność nie można znaleźć w obiekcie, jego [[Prototype]] jest przeszukiwana w zamian.Jeden scenariusz użycia: powiedzmy, że chcesz dodać właściwość do wszystkich obiektów, możesz po prostu dodać ją do Object.prototype, która automatycznie zastosuje się do wszystkich obiektów, ponieważ wszystkie obiekty mają w jakiś sposób Object.prototype swój rdzeń łańcucha [[Prototype]].

Powróćmy do właściwości funkcji obiektu "" prototype ". Jest to użyteczne tylko w połączeniu z operatorem new. Weźmy następujący fragment kodu jako przykład:

function F() {} // function declaration 
// F now has a property named "prototype" 

var f = new F(); // use "new" operator to create a new function object based on F 

Co new F() robi powyżej jest najpierw utworzyć nowy obiekt funkcji, ustaw [[Prototype]] (ukryty link) tego nowo utworzonego obiektu funkcyjnego być F.prototype, a następnie zawróci nowy obiekt funkcji. Prawdopodobnie to już wiesz, że działa dla obiektów funkcji.

Pamiętaj, że powiedziałem, że nie możemy zmienić obiektu [[Prototype]]? Cóż, przynajmniej nie bezpośrednio. Funkcja Crockforda Object.create właśnie to robi, wykorzystując fakt, że operator new może pomóc nam ustawić [[Prototype]] dla nas. Tak więc, używając Object.create, celowo wskazujesz, gdzie powinien wskazywać ukryty link twojego nowego obiektu. (nieco ochotę wskazać, kto jest twoją rodzicielską klasą)

W twoim przykładzie, conf jest literałem obiektu, a conf.prototype nie jest zbyt użyteczny. Oto kolejna wersja wykorzystując klasyczny styl:

function ConfBase() {} 
ConfBase.prototype.d = 16; 
var conf = new ConfBase(); 
conf.a = 2; 
conf.b = 4; 

document.writeln(conf.a); 
document.writeln(conf.b); 
document.writeln(conf.d); 

porównaniu odpowiedzią @CMS, ja wolę korzystania Object.create. Ale zasadniczo 2 style używają tego samego podstawowego mechanizmu, tylko że Object.create pomaga uporządkować to.

Powiązane problemy