Frage

I'been eine Erbschaft in js tun, um es besser zu verstehen, und ich habe etwas gefunden, das mich verwirrt.

Ich weiß, dass, wenn Sie eine ‚Konstruktorfunktion‘ rufen mit dem neuen Schlüsselwort, Sie zu dieser Funktion des Prototyps ein neues Objekt mit einem Verweis erhalten.

Ich weiß auch, dass, um prototypische Vererbung machen Sie mit einer Instanz des Objekts den Prototyp der Konstruktorfunktion ersetzen müssen Sie die ‚Superklasse‘ sein wollen.

Also habe ich dieses dumme Beispiel diese Konzepte versuchen:

function Animal(){}
function Dog(){}

Animal.prototype.run = function(){alert("running...")};

Dog.prototype = new Animal(); 
Dog.prototype.bark = function(){alert("arf!")};

var fido = new Dog();
fido.bark() //ok
fido.run() //ok

console.log(Dog.prototype) // its an 'Object' 
console.log(fido.prototype) // UNDEFINED
console.log(fido.constructor.prototype == Dog.prototype) //this is true

function KillerDog(){};
KillerDog.prototype.deathBite = function(){alert("AAARFFF! *bite*")}

fido.prototype = new KillerDog();

console.log(fido.prototype) // no longer UNDEFINED
fido.deathBite(); // but this doesn't work!

(Dies wurde in Firebug Konsole getan)

1) Warum, wenn alle neuen Objekte eine Referenz auf die Schöpfer Funktion des Prototyps enthalten, fido.prototype ist nicht definiert?

2) Ist die Vererbungskette [obj] -> [Konstruktor] -> [Prototyp] anstelle von [obj] -> [Prototyp]

3) wird das ‚Prototyp‘ Eigentum unseres Objekts (fido) jemals überprüft? wenn ja ... warum ist 'deathBite' undefined (im letzten Teil)?

War es hilfreich?

Lösung

  

1) Warum, wenn alle neuen Objekte enthalten ein   Bezug auf den Schöpfer Funktion   Prototyp, fido.prototype ist   undefined?

Alle neuen Objekte halten Sie einen Verweis auf den Prototyp, der auf ihrem Konstruktor zum Zeitpunkt der Konstruktion vorlag. Allerdings verwendet der Name der Eigenschaft dieser Referenz zu speichern ist nicht prototype, wie es auf den Konstruktor Funktion selbst ist. Einige Javascript-Implementierungen erlauben den Zugang zu diesem ‚versteckten‘ Eigentum über einige Eigenschaftsnamen wie __proto__ wo andere nicht (zum Beispiel Microsofts).

  

2) Ist die Vererbungskette [obj] ->   [Konstruktor] -> [Prototyp] statt   von [obj] -> [Prototyp]

Nein. Werfen Sie einen Blick auf diese: -

function Base() {}
Base.prototype.doThis = function() { alert("First"); }

function Base2() {}
Base2.prototype.doThis = function() { alert("Second"); }

function Derived() {}
Derived.prototype = new Base()

var x = new Derived()

Derived.prototype = new Base2()

x.doThis();

Diese Warnungen "First" nicht Zweiter. Wenn die Vererbungskette über den Konstruktor ging würden wir „Second“ sehen. Wenn ein Objekt die aktuelle Referenz in der Funktionsprototyp Eigenschaft gehalten aufgebaut ist, das Objekt versteckt Bezug auf dessen Prototyp übertragen wird.

  

3) ist der ‚Prototyp‘ Eigentum unserer   Objekt (fido) jemals überprüft? wenn ja...   warum ist 'deathBite' undefined (in der   letzter Teil)?

Zuordnung zu einem Objekt (außer Funktion) eine Eigenschaft namens prototype keine besondere Bedeutung hat, wie bereits erwähnt ein Objekt halten keinen Hinweis auf dessen Prototyp über einen solchen Eigenschaftsnamen.

Andere Tipps

Sie können nicht ein Objekt der Prototyp ändern, sobald es mit new instanziiert worden ist.

In Ihrem Beispiel oben, Zeilen wie

fido.prototype = new KillerDog();

erstellt einfach ein neues Attribut prototype auf dem Objekt fido benannt und setzt dieses Attribut auf ein neues KillerDog Objekt. Es ist nicht anders als

fido.foo = new KillerDog();

Wie der Code steht ...

// Doesn't work because objects can't be changed via their constructors
fido.deathBite();

// Does work, because objects can be changed dynamically, 
// and Javascript won't complain when you use prototype 
//as an object attribute name
fido.prototype.deathBite();

Das besondere prototype Verhalten gilt nur für Konstrukteure in Javascript, wo Konstrukteure sind functions, die mit new aufgerufen werden.

Antwort von Zahlen auf Ihre Fragen:

  1. den Prototyp des Objekts Eigenschaft nicht prototype genannt. Der Standard verwendet [[prototype]] es zu bezeichnen. Firefox macht diese Eigenschaft Öffentlichkeit unter dem Namen __proto __.
  2. Die Vererbungskette ist [obj][prototype object]. Ihre ursprüngliche Annahme ([obj][constructor][prototype]) ist falsch und man kann es leicht entkräften durch constructor Modifizieren und / oder constructor.prototype, und die Überprüfung, welche Methoden auf Ihrem [obj] aufgerufen werden können - Sie werden feststellen, dass diese Änderungen nicht alles ändern
  3. prototype Eigenschaft auf Objekte werden nicht überprüft und nicht verwendet. Sie können es einstellen, was auch immer Sie mögen. JavaScript verwendet es auf Funktion nur während des Objekts Bauobjekte.

die # Um zu demonstrieren, 3 hier ist der Code von Dojo :

dojo.delegate = dojo._delegate = (function(){
  // boodman/crockford delegation w/ cornford optimization
  function TMP(){}
  return function(obj, props){
    TMP.prototype = obj;
    var tmp = new TMP();
    if(props){
      dojo._mixin(tmp, props);
    }
    return tmp; // Object
  }
})();

Wie Sie sehen können es sich die Tatsache zunutze, dass nimmt prototype nur an einem Ort verwendet wird, durch die gleiche Funktion TMP für alle delegierten Objekte mit verschiedenen Prototypen Wiederverwendung. In der Tat ist prototype direkt vor dem Aufruf der Funktion mit new zugewiesen, und es wird danach nicht beeinflussen alle erstellten Objekte geändert werden.

Sie können das Objekt erstellt Sequenz in meiner Antwort finden href="https://stackoverflow.com/questions/383201/relation-between-prototype-and-prototype-in-javascript#383478"> Relation zum .

Ich weiß, es ist schon beantwortet worden, aber es gibt einen besseren Weg, Vererbung zu tun. einen Konstruktor nur zum Zweck der Vererbung Aufruf ist nicht wünschenswert. Eine der unerwünschten Wirkungen ist.

function Base() {this.a = "A"}
function Child() {this.b = "B"};

Child.prototype = new Base();

Jetzt haben Sie zusätzliche Eigenschaft „a“ zum Prototyp des Kindes, die Sie nicht wollen.

Hier ist die richtige Art und Weise (ich habe das nicht erfunden, Ext-JS und andere Libs verwenden diese)

// This is used to avoid calling a base class's constructor just to setup inheritance.
function SurrogateCtor() {}

/**
 * Sets a contructor to inherit from another constructor
 */
function extend(BaseCtor, DerivedCtor) {
  // Copy the prototype to the surrogate constructor
  SurrogateCtor.prototype = BaseCtor.prototype;
  // this sets up the inheritance chain
  DerivedCtor.prototype = new SurrogateCtor();
  // Fix the constructor property, otherwise it would point to the BaseCtor
  DerivedCtor.prototype.constructor = DerivedCtor;
  // Might as well add a property to the constructor to 
  // allow for simpler calling of base class's method
  DerivedCtor.superclass = BaseCtor;
}

function Base() {
  this.a = "A";
}

Base.prototype.getA = function() {return this.a}

function Derived() {
  Derived.superclass.call(this);  // No need to reference the base class by name
  this.b = "B";
}

extend(Base, Derived);
// Have to set methods on the prototype after the call to extend
// otherwise the prototype is overridden;
Derived.prototype.getB = function(){return this.b};
var obj = new Derived();

Eine noch einfachere Art und Weise ist ein dritten Parameter hinzuzufügen, zu erweitern, in dem Sie die Methode der abgeleiteten Klasse angeben, so dass Sie mit dem Prototyp nicht aufrufe erweitern und fügen Sie dann Methoden

extend(BaseCtor, DerivedCtor, {
  getB: function() {return this.b}
});

Dann gibt es viele anderen Dinge, die Sie für syntaktischen Zucker tun könnten.

darüber gebloggt: http: // js -bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

erwähnenswert, dass in ECMAScript 5 (dh die neueste Version der JavaScript-Sprache) können Sie den Zugriff auf den internen [[Prototyp]] erhalten Eigenschaft einer Instanz über Object.getPrototypeOf :

Object.getPrototypeOf(fido) === Dog.prototype
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top