Domanda

I'been fare un po 'eredità in js al fine di comprendere meglio, e ho trovato qualcosa che mi confonde.

So che quando si chiama un 'funzione di costruzione' con la nuova parola chiave, si ottiene un nuovo oggetto con un riferimento al prototipo di quella funzione.

So anche che al fine di rendere l'ereditarietà prototipale è necessario sostituire il prototipo della funzione di costruzione con un'istanza dell'oggetto che si desidera essere il 'superclasse'.

Così ho fatto questo stupido esempio per provare questi concetti:

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!

(Questo è stato fatto in console di Firebug)

1) Perché se tutti i nuovi oggetti contengono un riferimento alla prototipo della funzione creatore, fido.prototype è indefinito?

2) è la catena di ereditarietà [obj] -> [costruttore] -> [prototype] invece di [obj] -> [prototype]

3) è la proprietà 'prototipo' del nostro oggetto (fido) mai verificato? se è così ... perché è 'deathBite' indefinito (nella parte finale)?

È stato utile?

Soluzione

  

1) Perché se tutti i nuovi oggetti contengono una   il riferimento al Creatore la funzione di   prototipo, fido.prototype è   undefined?

Tutti i nuovi oggetti fanno mantenere un riferimento al prototipo che era presente sul loro costruttore al momento della costruzione. Tuttavia il nome proprietà utilizzata per memorizzare questo riferimento non è prototype in quanto è la funzione di costruzione stessa. Alcune implementazioni Javascript Impedire l'accesso a questa proprietà 'nascosto' con un nome proprietà come __proto__ dove gli altri non (per esempio Microsofts).

  

2) è la catena di ereditarietà [obj] ->   [Costruttore] -> [prototype] invece   di [obj] -> [prototype]

No. Date un'occhiata a questo: -

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();

È il segnale per "First" non Seconda. Se la catena di ereditarietà è andato tramite il costruttore vorremmo vedere "Secondo". Quando un oggetto viene costruito il riferimento corrente intrattenuto nella proprietà Funzioni prototipo è trasferito al di oggetti nascosti riferimento al suo prototipo.

  

3) è il 'prototipo' di proprietà della nostra   oggetto (fido) mai verificato? se è così...   perché è 'deathBite' indefinito (nel   ultima parte)?

L'assegnazione ad un oggetto (diverso da una funzione) una proprietà denominata prototype non ha alcun significato particolare, come affermato in precedenza un oggetto non mantiene un riferimento al suo prototipo tramite tale nome della proprietà.

Altri suggerimenti

Non è possibile modificare il prototipo di un oggetto una volta che è stato istanziato con new.

Nel tuo esempio sopra, le linee come

fido.prototype = new KillerDog();

semplicemente crea un nuovo attributo denominato prototype sul fido oggetto, e imposta tale attributo a un nuovo oggetto KillerDog. Non è diverso rispetto

fido.foo = new KillerDog();

Per quanto il codice si trova ...

// 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();

Il comportamento speciale prototype si applica solo ai costruttori in JavaScript, in cui i costruttori sono functions che verranno chiamati con new.

Risposta dai numeri alle tue domande:

  1. proprietà prototype di oggetto non si chiama prototype. Lo standard utilizza [[prototype]] per designare esso. Firefox rende questa proprietà pubblica con il nome di __proto __.
  2. La catena di ereditarietà è [obj] [prototype object] ⇒. La tua ipotesi originale ([obj][constructor][prototype]) non è corretto e si può facilmente confutarla, modificando constructor e / o constructor.prototype, e controllando quali metodi possono essere chiamati sul [obj] - si scopre che queste modifiche non cambiano nulla
  3. proprietà prototype su oggetti non vengono controllati e non utilizzati. È possibile impostare per quello che vuoi. JavaScript utilizza su oggetti funzione solo durante la costruzione di un oggetto.

Per dimostrare la # 3 ecco il codice da 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
  }
})();

Come si può vedere si avvantaggia del fatto che prototype viene utilizzato solo in un luogo riutilizzando la stessa funzione TMP per tutti gli oggetti delegati con differenti prototipi. Infatti prototype viene assegnato direttamente prima di richiamare la funzione con new, e sarà cambiato dopo che non interessano tutti gli oggetti creati.

È possibile trovare la sequenza creata oggetto nella mia risposta a tra [[Prototype]] e prototipi in JavaScript .

Lo so che è già stato risposto, ma, c'è un modo migliore per farlo eredità. Chiamare un costruttore solo per lo scopo di eredità non è auspicabile. Uno degli effetti indesiderati è.

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

Child.prototype = new Base();

proprietà ora hai aggiunto "a" al prototipo del bambino che non hai intenzione di.

Ecco la strada giusta (non ho inventato questo, Ext-JS e le altre librerie usano questo)

// 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();

Un modo ancora più semplice è quello di aggiungere un terzo parametro per estendere in cui si specifica il metodo della classe derivata in modo che non c'è bisogno di chiamare estendere e quindi aggiungere i metodi al prototipo

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

Poi ci sono molte altre cose che si potrebbe fare per lo zucchero sintattico.

bloggato su esso: http: // js -bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

Da segnalare che in ECMAScript 5 (vale a dire la versione più recente del linguaggio JavaScript) è possibile ottenere l'accesso al interno [[Prototype]] di proprietà di un'istanza tramite Object.getPrototypeOf :

Object.getPrototypeOf(fido) === Dog.prototype
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top