Va bene, giochiamo un po 'di gioco di mente:

dall'immagine qui sopra possiamo vedere:
- Quando creiamo una funzione come
function Foo() {}
, JavaScript crea un'istanza Function
.
- Ogni istanza
Function
(la funzione di costruzione) ha una proprietà prototype
che è un puntatore.
- La proprietà
prototype
della funzione di costruzione punta al suo oggetto prototipo.
- L'oggetto prototipo ha una proprietà
constructor
che è anche un puntatore.
- La proprietà
constructor
dell'oggetto prototipo fa riferimento alla sua funzione di costruzione.
- Quando creiamo una nuova istanza di come
new Foo()
, JavaScript crea un nuovo oggetto.
- La proprietà interna di
[[proto]]
dell'istanza punta al prototipo del costruttore.
Ora, la domanda sorge spontanea perché perché JavaScript non attribuisce la proprietà constructor
all'oggetto istanza invece del prototipo. Considerate:
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
var Square = defclass({
constructor: function (side) {
this.side = side;
},
area: function() {
return this.side * this.side;
}
});
var square = new Square(10);
alert(square.area()); // 100
Come si può vedere la proprietà constructor
è solo un altro metodo del prototipo, come area
nell'esempio di cui sopra. Ciò che rende speciale la proprietà constructor
è che viene utilizzato per inizializzare un'istanza del prototipo. Altrimenti è esattamente la stessa di qualsiasi altro metodo del prototipo.
Definire la proprietà constructor
sul prototipo è vantaggiosa per i seguenti motivi:
- E 'logicamente corretto. Ad esempio, considerare
Object.prototype
. La proprietà constructor
di Object.prototype
punta a Object
. Se la proprietà constructor
è stata definita sull'istanza, allora Object.prototype.constructor
sarebbe undefined
perché Object.prototype
è un'istanza di null
.
- Non viene trattato in modo diverso dagli altri metodi di prototipazione. Ciò semplifica il lavoro di
new
poiché non è necessario definire la proprietà constructor
su ogni istanza.
- Ogni istanza condivide la stessa proprietà
constructor
. Quindi è efficiente.
Ora, quando si parla di eredità, abbiamo la seguente scenario:

dall'immagine qui sopra possiamo vedere:
- proprietà del costruttore derivato
prototype
è impostato su l'istanza del costruttore base.
- Quindi la proprietà interna
[[proto]]
dell'istanza del costruttore derivato punta anche a esso.
- Pertanto la proprietà
constructor
dell'istanza del costruttore derivata punta ora al costruttore base.
Per quanto riguarda il instanceof
dell'operatore, contrariamente alla credenza popolare che non dipende dalla constructor
proprietà dell'istanza. Come possiamo vedere dall'alto, ciò porterebbe a risultati errati.
L'operatore instanceof
è un operatore binario (ha due operandi). Funziona su un oggetto istanza e una funzione costruttore. Come spiegare il Mozilla Developer Network, lo fa semplicemente il seguente:
function instanceOf(object, constructor) {
while (object != null) {
if (object == constructor.prototype) { //object is instanceof constructor
return true;
} else if (typeof object == 'xml') { //workaround for XML objects
return constructor.prototype == XML.prototype;
}
object = object.__proto__; //traverse the prototype chain
}
return false; //object is not instanceof constructor
}
Per dirla semplicemente, se Foo
eredita da Bar
, allora la catena di prototipi per l'istanza di Foo
sarebbe:
foo.__proto__ === Foo.prototype
foo.__proto__.__proto__ === Bar.prototype
foo.__proto__.__proto__.__proto__ === Object.prototype
foo.__proto__.__proto__.__proto__.__proto__ === null
Come si può vedere, ogni oggetto eredita dal costruttore Object
. La catena del prototipo termina quando una proprietà interna [[proto]]
punta a null
.
La funzione instanceof
attraversa semplicemente la catena di prototipi dell'oggetto dell'istanza (il primo operando) e confronta il [[proto]]
struttura interna di ciascun oggetto alla prototype
proprietà della funzione di costruzione (il secondo operando). Se corrispondono, restituisce true
; e se la catena del prototipo termina, restituisce false
.
Qualsiasi motivo per cui è necessario aggiornare il costruttore? Trovo che la mia vita sia più facile se faccio finta che la proprietà non esista. – hugomg
Sto facendo fatica a chiuderlo come duplicato - tutti gli altri questini sono così prolissi ... – hugomg
'c.prototype' è' b() 'e' b.prototype' è 'a()', quindi 'c.prototype' è' a() ' –