Questa figura mostra ancora che ogni object ha un prototipo. Funzione di costruzione Foo ha anche il suo
__proto__
che è Function.prototype e che a sua volta fa riferimento anche tramite la sua proprietà__proto__
al Object.prototype. Quindi, ripetiamo, Foo.prototype è solo una proprietà esplicita di Foo che si riferisce al prototipo di oggetti b e c.
var b = new Foo(20); var c = new Foo(30);
Quali sono le differenze tra __proto__
e le proprietà del prototype
?
La figura è presa da qui .
__proto__
è l’object reale che viene utilizzato nella catena di ricerca per risolvere i metodi, ecc. prototype
è l’object che viene utilizzato per creare __proto__
quando si crea un object con new
:
( new Foo ).__proto__ === Foo.prototype; ( new Foo ).prototype === undefined;
prototype
è una proprietà di un object Function. È il prototipo di oggetti costruiti da quella funzione.
__proto__
è la proprietà interna di un object, che punta al suo prototipo. Gli standard attuali forniscono un metodo Object.getPrototypeOf(O)
equivalente, sebbene lo standard __proto__
sia più veloce.
Puoi trovare l’ instanceof
relazioni confrontando il prototype
di una __proto__
catena __proto__
di un object e puoi interrompere queste relazioni modificando il prototype
.
function Point(x, y) { this.x = x; this.y = y; } var myPoint = new Point(); // the following are all true myPoint.__proto__ == Point.prototype myPoint.__proto__.__proto__ == Object.prototype myPoint instanceof Point; myPoint instanceof Object;
Qui Point
è una funzione di costruzione, costruisce un object (struttura dati) proceduralmente. myPoint
è un object costruito da Point()
quindi Point.prototype
viene salvato su myPoint.__proto__
in quel momento.
La proprietà Prototype viene creata quando viene dichiarata una funzione.
Per esempio:
function Person(dob){ this.dob = dob };
La proprietà person.prototype viene creata internamente una volta dichiarata la funzione precedente. Molte proprietà possono essere aggiunte al Person.prototype che sono condivise dalle istanze Person create usando new Person ().
// adds a new method age to the Person.prototype Object. Person.prototype.age = function(){return date-dob};
Vale la pena notare che Person.prototype
è un Object
letterale per impostazione predefinita (può essere modificato come richiesto).
Ogni istanza creata utilizzando la nuova Persona () ha una proprietà __proto__
che punta al Person.prototype. Questa è la catena che viene utilizzata per attraversare per trovare una proprietà di un particolare object.
var person1 = new Person(somedate); var person2 = new Person(somedate);
crea 2 istanze di Person, questi 2 oggetti possono chiamare la proprietà age di Person.prototype come person1.age, person2.age.
Nell’immagine sopra puoi vedere che Foo è un object funzione e quindi ha un collegamento __proto__
al Function.prototype che a sua volta è un’istanza di Object e ha un collegamento __proto__ a Object.prototype. Il collegamento proto termina qui con __proto__
nel Object.prototype che punta a null.
Qualsiasi object può avere accesso a tutte le proprietà nella sua catena di proto come collegate da __proto__
, formando così la base per l’ereditarietà prototipale.
__proto__
non è un modo standard per accedere alla catena del prototipo, l’approccio standard ma simile è quello di utilizzare Object.getPrototypeOf (obj).
Il codice sottostante per l’operatore instanceof
fornisce una migliore comprensione:
object instanceof
operatore di class restituisce true
quando un object è un’istanza di una class, in particolare se si trova Class.prototype
nella catena di proto di quell’object, quindi l’object è un’istanza di tale class.
function instanceOf(Func){ var obj = this; while(obj !== null){ if(Object.getPrototypeOf(obj) === Func.prototype) return true; obj = Object.getPrototypeOf(obj); } return false; }
Il metodo sopra può essere chiamato come: instanceOf.call(object,Class)
che restituisce true se object è istanza di Class.
Un bel modo di pensarci è …
prototype
è usato dalle funzioni del constructor()
. Dovrebbe essere stato davvero chiamato qualcosa come "prototypeToInstall"
, dal momento che è quello che è.
e __proto__
è quel “prototipo installato” su un object (che è stato creato / installato sull’object da detta funzione constructor()
)
Quando si crea una funzione, un object proprietà chiamato prototype viene creato automaticamente (non lo si è creato personalmente) e viene collegato all’object function (il constructor
).
Nota : questo nuovo object prototipo punta o ha un collegamento interno-privato con l’object JavaScript nativo.
Esempio:
function Foo () { this.name = 'John Doe'; } // Foo has an object property called prototype. // prototype was created automatically when we declared the function Foo. Foo.hasOwnProperty('prototype'); // true // Now, we can assign properties and methods to it: Foo.prototype.myName = function () { return 'My name is ' + this.name; }
Se creerai un nuovo object fuori da Foo
usando la new
parola chiave, crei fondamentalmente (tra le altre cose) un nuovo object che ha un link interno o privato al prototipo Foo
della funzione che abbiamo discusso in precedenza:
var b = new Foo(); b.[[Prototype]] === Foo.prototype // true
Il collegamento privato all’object di quella funzione chiamato prototipo di parentesi doppia o solo [[Prototype]]
. Molti browser ci forniscono un collegamento pubblico ad esso che si chiama __proto__
!
Per essere più specifici, __proto__
è in realtà una funzione getter che appartiene all’object JavaScript nativo. Restituisce il collegamento prototipo interno-privato di qualunque sia il legame (restituisce [[Prototype]]
di b
):
b.__proto__ === Foo.prototype // true
Vale la pena notare che l’avvio di ECMAScript5
, è ansible utilizzare anche il metodo getPrototypeOf per ottenere il collegamento privato interno:
Object.getPrototypeOf(b) === b.__proto__ // true
NOTA: questa risposta non intende coprire l’intero processo di creazione di nuovi oggetti o nuovi costruttori, ma per aiutare a capire meglio cosa è __proto__
, prototype
e [[Prototype]]
e come funziona.
Per spiegarci, creiamo una funzione
function a (name) { this.name = name; }
Quando JavaScript esegue questo codice, aggiunge la proprietà prototype
a a
proprietà prototype
è un object con due proprietà:
constructor
__proto__
Quindi quando lo facciamo
a.prototype
restituisce
constructor: a // function definition __proto__: Object
Ora come puoi vedere il constructor
non è altro che la funzione a
se stessa e __proto__
punta al livello radice Object
di JavaScript.
Vediamo cosa succede quando usiamo a
funzione con una new
parola chiave.
var b = new a ('JavaScript');
Quando JavaScript esegue questo codice, fa 4 cose:
__proto__
su b
e punta a a.prototype
così b.__proto__ === a.prototype
a.prototype.constructor
(che è la definizione della funzione a
) con l’object appena creato (creato nel passaggio # 1) come suo contesto (this), quindi la proprietà name
passata come ‘JavaScript’ (che viene aggiunta a this
) viene aggiunto all’object appena creato. b
venga assegnato all’object appena creato. Ora se aggiungiamo a.prototype.car = "BMW"
e facciamo b.car
, b.car
l’uscita “BMW”.
questo perché quando JavaScript ha eseguito questo codice ha cercato la proprietà car
su b
, non ha trovato JavaScript utilizzato b.__proto__
(che è stato fatto per puntare a ‘a.prototype’ nel passaggio # 2) e trova la proprietà della car
in modo da restituire ” BMW”.
Per renderlo un po ‘più chiaro oltre alle ottime risposte di cui sopra:
function Person(name){ this.name = name }; var eve = new Person("Eve"); eve.__proto__ == Person.prototype //true eve.prototype //undefined
Le istanze hanno __proto__ , le classi hanno un prototipo .
Un altro buon modo per capirlo:
var foo = {} /* foo.constructor is Object, so foo.constructor.prototype is actually Object.prototype; Object.prototype in return is what foo.__proto__ links to. */ console.log(foo.constructor.prototype === foo.__proto__); // this proves what the above comment proclaims: Both statements evaluate to true. console.log(foo.__proto__ === Object.prototype); console.log(foo.constructor.prototype === Object.prototype);
Solo dopo IE11 __proto__
è supportato. Prima di quella versione, come IE9, si poteva usare il constructor
per ottenere il __proto__
.
Mi capita di imparare il prototipo di You Do not Know JS: questo e Object Prototypes , che è un libro meraviglioso per capire il design sottostante e chiarire così tante idee sbagliate (ecco perché sto cercando di evitare l’uso dell’ereditarietà e cose come instanceof
) .
Ma ho la stessa domanda delle persone qui poste. Diverse risposte sono davvero utili e illuminanti. Mi piacerebbe anche condividere le mie comprensioni.
Gli oggetti in JavaScript hanno una proprietà interna, indicata nella specifica come [[Prototype]]
, che è semplicemente un riferimento a un altro object. Quasi tutti gli oggetti hanno un valore non null
per questa proprietà, al momento della loro creazione.
tramite __proto__
o Object.getPrototypeOf
var a = { name: "wendi" }; a.__proto__ === Object.prototype // true Object.getPrototypeOf(a) === Object.prototype // true function Foo() {}; var b = new Foo(); b.__proto__ === Foo.prototype b.__proto__.__proto__ === Object.prototype
prototype
? prototype
è un object creato automaticamente come una proprietà speciale di una funzione , che viene utilizzata per stabilire la catena di delega (ereditarietà), ovvero la catena del prototipo.
Quando creiamo una funzione a
, il prototype
viene automaticamente creato come una proprietà speciale su ae salva il codice funzione come constructor
su prototype
.
function Foo() {}; Foo.prototype // Object {constructor: function} Foo.prototype.constructor === Foo // true
Mi piacerebbe considerare questa proprietà come il luogo in cui memorizzare le proprietà (compresi i metodi) di un object funzione. Questo è anche il motivo per cui le funzioni di utilità in JS sono definite come Array.prototype.forEach()
, Function.prototype.bind()
, Object.prototype.toString().
Perché sottolineare la proprietà di una funzione ?
{}.prototype // undefined; (function(){}).prototype // Object {constructor: function} // The example above shows object does not have the prototype property. // But we have Object.prototype, which implies an interesting fact that typeof Object === "function" var obj = new Object();
Quindi, Arary
, Function
, Object
sono tutte funzioni. Devo ammettere che questo rinfresca la mia impressione su JS. So che le funzioni sono di prima class in JS, ma sembra che sia basato su funzioni.
__proto__
e prototype
? __proto__
un riferimento funziona su ogni object per fare riferimento alla sua proprietà [[Prototype]]
.
prototype
è un object creato automaticamente come una proprietà speciale di una funzione , che viene utilizzata per memorizzare le proprietà (compresi i metodi) di un object funzione.
Con questi due, potremmo mappare mentalmente la catena del prototipo. Come questa immagine illustra:
function Foo() {} var b = new Foo(); b.__proto__ === Foo.prototype // true Foo.__proto__ === Function.prototype // true Function.prototype.__proto__ === Object.prototype // true
In JavaScript, una funzione può essere utilizzata come costruttore. Ciò significa che possiamo creare oggetti con la nuova parola chiave. Ogni funzione del costruttore viene fornita con un object incorporato incatenato con loro. Questo object built-in è chiamato prototipo. Instances of a constructor function use __proto__ to access the prototype property of its constructor function.
Per prima cosa abbiamo creato un costruttore: function Foo(){}
. Per essere chiari, Foo è solo un’altra funzione. Ma possiamo creare un object da esso con la nuova parola chiave. Ecco perché la chiamiamo la funzione di costruzione
Ogni funzione ha una proprietà unica che viene chiamata proprietà prototipo. Quindi, la funzione di costruzione Foo
ha una proprietà prototipo che punta al suo prototipo, che è Foo.prototype
(vedi immagine).
Le funzioni di costruzione sono esse stesse una funzione che è un’istanza di un costruttore di sistema chiamato costruttore [[Funzione]]. Quindi possiamo dire che la function Foo
è costruita da un costruttore [[Funzione]]. Quindi, __proto__
della nostra Foo function
punterà al prototipo del suo costruttore, che è Function.prototype
.
Function.prototype
è esso stesso nient’altro che un object che è costruito da un altro costruttore di sistema chiamato [[Object]]
. Quindi [[Object]]
è il costruttore di Function.prototype
. Quindi, possiamo dire che Function.prototype
è un’istanza di [[Object]]
. Quindi __proto__
di Function.prototype
punta a Object.prototype
.
Object.prototype
è l’ultimo uomo presente nella catena del prototipo. Voglio dire che non è stato costruito. È già presente nel sistema. Quindi il suo __proto__
punta a null
.
Ora veniamo alle istanze di Foo
. Quando creiamo un’istanza usando il new Foo()
, crea un nuovo object che è un’istanza di Foo
. Ciò significa che Foo
è il costruttore di queste istanze. Qui abbiamo creato due istanze (xey). __proto__
di x e y indica quindi Foo.prototype
.
Per dirla semplicemente:
> var a = 1 undefined > a.__proto__ [Number: 0] > Number.prototype [Number: 0] > Number.prototype === a.__proto__ true
Ciò consente di colbind le proprietà a X.prototype DOPO che gli oggetti di tipo X sono stati istanziati e continueranno ad accedere a tali nuove proprietà tramite il riferimento __proto__ che il motore JavaScript utilizza per risalire la catena del prototipo.
prototipo è una proprietà di una funzione. È il progetto per la creazione di oggetti usando la funzione (costruttore) con una nuova parola chiave.
__proto__
è usato nella catena di ricerca per risolvere metodi, proprietà. quando viene creato un object (utilizzando la funzione di costruzione con una nuova parola chiave), __proto__
è impostato su (Constructor) Function.prototype
function Robot(name) { this.name = name; } var robot = new Robot(); // the following are true robot.__proto__ == Robot.prototype robot.__proto__.__proto__ == Object.prototype
Immagina che ci sia una class immaginaria (blueprint / coockie cutter) associata alla funzione. Quella class immaginaria è usata per istanziare oggetti. prototype
è il meccanismo di estensione (metodo di estensione in C # o Swift Extension) per aggiungere elementi a quella class immaginaria.
function Robot(name) { this.name = name; }
Quanto sopra può essere immaginato come:
// imaginary class class Robot extends Object{ static prototype = Robot.class // Robot.prototype is the way to add things to Robot class // since Robot extends Object, therefore Robot.prototype.__proto__ == Object.prototype var __proto__; var name = ""; // constructor function Robot(name) { this.__proto__ = prototype; prototype = undefined; this.name = name; } }
Così,
var robot = new Robot(); robot.__proto__ == Robot.prototype robot.prototype == undefined robot.__proto__.__proto__ == Object.prototype
Ora aggiungendo il metodo al prototype
di Robot:
Robot.prototype.move(x, y) = function(x, y){ Robot.position.x = x; Robot.position.y = y}; // Robot.prototype.move(x, y) ===(imagining)===> Robot.class.move(x, y)
Quanto sopra può essere immaginato come estensione della class Robot:
// Swift way of extention extension Robot{ function move(x, y){ Robot.position.x = x; Robot.position.y = y } }
Che a loro volta,
// imaginary class class Robot{ static prototype = Robot.class // Robot.prototype way to extend Robot class var __proto__; var name = ""; // constructor function Robot(name) { this.__proto__ = prototype; prototype = undefined; this.name = name; } // added by prototype (as like C# extension method) function move(x, y){ Robot.position.x = x; Robot.position.y = y }; }
Prototype o Object.prototype è una proprietà di un object letterale. Rappresenta l’ object prototipo dell’object che è ansible sovrascrivere per aggiungere ulteriori proprietà o metodi lungo la catena del prototipo.
__proto__ è una proprietà accessoria (funzione get e set) che espone il prototipo interno di un object attraverso il quale è accessibile.
Riferimenti:
Lo so, sono in ritardo ma lascia che provi a semplificarlo.
Diciamo che c’è una funzione
function Foo(message){ this.message = message ; }; console.log(Foo.prototype);
La funzione Foo avrà un object prototipo collegato. Quindi, ogni volta che creiamo una funzione in JavaScript, ha sempre un object prototipo ad esso collegato.
Ora andiamo avanti e creiamo due oggetti usando la funzione Foo.
var a = new Foo("a"); var b = new Foo("b"); console.log(a.message); console.log(b.message);
Ora, Foo.prototype, a. proto e b. proto all denota lo stesso object.
b.__proto__ === Object.getPrototypeOf(a); a.__proto__ === Foo.prototype; a.constructor.prototype === a.__proto__;
tutto quanto sopra sarebbe tornato vero.
Come sappiamo, in JavaScript le proprietà possono essere aggiunte dynamicmente. Possiamo aggiungere proprietà a object
Foo.prototype.Greet = function(){ console.log(this.message); } a.Greet();//a b.Greet();//b a.constructor.prototype.Greet();//undefined
Come vedi abbiamo aggiunto il metodo Greet () in Foo.prototype, ma è accessibile in aeb o in qualsiasi altro object che è stato creato usando Foo.
Durante l’esecuzione di a.Greet (), JavaScript cercherà dapprima Greet nell’object a nell’elenco delle proprietà. Non trovando, salirà in proto chain di a. Da. proto e Foo.prototype è lo stesso object, JavaScript troverà il metodo Greet () e lo eseguirà.
Spero che ora prototipo e proto siano semplificati un po ‘.
(il numero all’interno della parentesi () è un “link” al codice che viene scritto di seguito)
prototype
: un object costituito da:
=> funzioni (3) di questo particolare ConstructorFunction.prototype
(5) accessibili da ciascun object (4) creato o creato da questa funzione costruttore (1)
=> la funzione di costruzione stessa (1)
=> __proto__
di questo object particolare (object prototipo)
__proto__
(dandor proto?) – un link TRA qualsiasi object (2) creato attraverso una particolare funzione di costruzione (1), AND le proprietà dell’object prototipo (5) di quel costruttore CHE permette a ciascun object creato (2) di avere accesso al prototipo funzioni e metodi (4) ( __proto__
è di default incluso in ogni singolo object in JS)
1.
function Person (name, age) { this.name = name; this.age = age; }
2.
var John = new Person('John', 37); // John is an object
3.
Person.prototype.getOlder = function() { this.age++; } // getOlder is a key that has a value of the function
4.
John.getOlder();
5.
Person.prototype;
Proverò una spiegazione di 4 ° grado:
Le cose sono molto semplici Un prototype
è un esempio di come qualcosa dovrebbe essere costruito. Così:
Sono una function
e costruisco nuovi oggetti simili al mio prototype
Sono un object
e sono stato costruito usando il mio __proto__
come esempio
prova :
function Foo() { } var bar = new Foo() // `bar` is constructed from how Foo knows to construct objects bar.__proto__ === Foo.prototype // => true // bar is an instance - it does not know how to create objects bar.prototype // => undefined
Ogni funzione creata ha una proprietà chiamata prototype
e inizia la sua vita come un object vuoto. Questa proprietà è inutile finché non si utilizza questa funzione come funzione di costruzione, ovvero con la parola chiave ‘new’.
Questo è spesso confuso con la proprietà __proto__
di un object. Alcuni potrebbero confondersi e ad eccezione del fatto che la proprietà prototype
di un object potrebbe ottenere il prototipo di un object. Ma questo non è un caso. prototype
è usato per ottenere il __proto__
di un object creato da un costruttore di funzioni.
Nell’esempio sopra:
function Person(name){ this.name = name }; var eve = new Person("Eve"); console.log(eve.__proto__ == Person.prototype) // true // this is exactly what prototype does, made Person.prototype equal to eve.__proto__
(function(){ let a = function(){console.log(this.b)}; a.prototype.b = 1; a.__proto__.b = 2; let q = new a(); console.log(ab); console.log(qb) })()
__proto__
è la base per build un prototype
e una funzione di costruzione, ad esempio: function human(){}
ha un prototype
che è condiviso tramite __proto__
nella nuova istanza della funzione di costruzione. Una lettura più dettagliata qui
'use strict' function A() {} var a = new A(); class B extends A {} var b = new B(); console.log('====='); // ===== console.log(B.__proto__ === A); // true console.log(B.prototype.__proto__ === A.prototype); // true console.log(b.__proto__ === B.prototype); // true console.log(a.__proto__ === A.prototype); // true console.log(A.__proto__ === Function.__proto__); // true console.log(Object.__proto__ === Function.__proto__); // true console.log(Object.prototype === Function.__proto__.__proto__); // true console.log(Object.prototype.__proto__ === null); // true
In JavaScript, ogni object (anche la funzione è object!) Ha una proprietà __proto__
, la proprietà fa riferimento al suo prototipo.
Quando usiamo il new
operatore con un costruttore per creare un nuovo object, la proprietà __proto__
del nuovo object sarà impostata con la proprietà prototype
del costruttore, quindi il costruttore sarà chiamato dal nuovo object, in quel processo “questo” sarà un riferimento a il nuovo object nello scope del costruttore, infine restituisce il nuovo object.
Constructor’s prototype is __proto__
property, Constructor’s prototype
property is work with the new
operator.
Constructor must be a function, but function not always is constructor even if it has prototype
property.
Prototype chain actually is object’s __proto__
property to reference its prototype, and the prototype’s __proto__
property to reference the prototype’s prototype, and so on, until to reference Object’s prototype’s __proto__
property which is reference to null.
Per esempio:
console.log(a.constructor === A); // true // "a" don't have constructor, // so it reference to A.prototype by its ``__proto__`` property, // and found constructor is reference to A
[[Prototype]]
and __proto__
property actually is same thing.
We can use Object’s getPrototypeOf method to get something’s prototype.
console.log(Object.getPrototypeOf(a) === a.__proto__); // true
Any function we written can be use to create an object with the new
operator, so anyone of those functions can be a constructor.
The __proto__
property of an object is a property that maps to the prototype
of the constructor function of the object. In altre parole:
instance.__proto__ === constructor.prototype // true
This is used to form the prototype
chain of an object. The prototype
chain is a lookup mechanism for properties on an object. If an object’s property is accessed Javascript will first look on the object itself, if the property isn’t found there it will climb up all the way up to protochain
until it is found (or not)
function Person (name, city) { this.name = name; } Person.prototype.age = 25; const willem = new Person('Willem'); console.log(willem.__proto__ === Person.prototype); // the __proto__ property on the instance refers to the prototype of the constructor console.log(willem.age); // 25 doesn't find it at willem object but is present at prototype console.log(willem.__proto__.age); // now we are directly accessing the prototype of the Person function
The proto property is a simple accessor property on Object.prototype consisting of a getter and setter function. A property access for proto that eventually consults Object.prototype will find this property, but an access that does not consult Object.prototype will not find it. If some other proto property is found before Object.prototype is consulted, that property will hide the one found on Object.prototype.
The proto getter function exposes the value of the internal [[Prototype]] of an object. For objects created using an object literal, this value is Object.prototype. For objects created using array literals, this value is Array.prototype. For functions, this value is Function.prototype. For objects created using new fun, where fun is one of the built-in constructor functions provided by JavaScript (Array, Boolean, Date, Number, Object, String, and so on — including new constructors added as JavaScript evolves), this value is always fun.prototype. For objects created using new fun, where fun is a function defined in a script, this value is the value of fun.prototype. (That is, if the constructor didn’t return an other object explicitly, or the fun.prototype has been reassigned since the instance was created).
The proto setter allows the [[Prototype]] of an object to be mutated. The object must be extensible according to Object.isExtensible(): if it is not, a TypeError is thrown. The value provided must be an object or null. Providing any other value will do nothing.
To understand how prototypes are used for inheritance, see guide article Inheritance and the prototype chain.
What about using __proto__
for static methods?
function Foo(name){ this.name = name Foo.__proto__.collection.push(this) Foo.__proto__.count++ } Foo.__proto__.count=0 Foo.__proto__.collection=[] var bar = new Foo('bar') var baz = new Foo('baz') Foo.count;//2 Foo.collection // [{...}, {...}] bar.count // undefined
my understanding is: __proto__ and prototype are all served for the prototype chain technique . the difference is functions named with underscore(like __proto__) are not aim for developers invoked explicitly at all. in other words, they are just for some mechanisms like inherit etc. they are ‘back-end’. but functions named without underscore are designed for invoked explicitly, they are ‘front-end’.
!!!THIS IS THE BEST EXPLANATION IN THE WORLD!!!!!
var q = {} var prototype = {prop: 11} q.prop // undefined q.__proto__ = prototype q.prop // 11
in function constructors javascript engine call this q.__proto__ = prototype
automatically when we write new Class
, and in to the __proto__
prop set Class.prototype
function Class(){} Class.prototype = {prop: 999} // set prototype as we need, before call new var q = new Class() // q.__proto__ = Class.prototype q.prop // 999
Enjoy %)