function Gadget(name, color)
{
this.name = name;
this.color = color;
}
Gadget.prototype.rating = 3
var newtoy = new Gadget("webcam", "black")
newtoy.constructor.prototype.constructor.prototype.constructor.prototype
Il retourne toujours l'objet avec rating = 3.
Mais si je fais ce qui suit:
newtoy.__proto__.__proto__.__proto__
La chaîne finit par retourner null
.
Aussi, dans Internet Explorer, comment vérifier la valeur NULL s'il n'y a pas de propriété __proto__
?
J'ai récemment essayé de comprendre ce que je pensais et j'ai finalement créé cette "carte" qui, je pense, donne toute la lumière sur la question.
http://i.stack.imgur.com/KFzI3.png
Je sais que je ne suis pas le premier à inventer cela, mais il était plus intéressant de le découvrir que le trouver :-). Quoi qu’il en soit, après cela, j’ai trouvé par exemple Ceci est un autre diagramme qui, à mon avis, dit fondamentalement la même chose:
Mise en page d'objets Javascript
La chose la plus surprenante pour moi a été de découvrir que Object.__proto__
pointe sur Function.prototype
, au lieu de Object.prototype
, mais je suis sûr qu'il y a une bonne raison à cela :-)
Je colle le code mentionné dans l'image ici aussi si quelqu'un veut le tester. Notez que certaines propriétés sont ajoutées aux objets pour vous permettre de savoir facilement où nous sommes après quelques sauts:
Object.O1='';
Object.prototype.Op1='';
Function.F1 = '';
Function.prototype.Fp1 = '';
Cat = function(){};
Cat.C1 = '';
Cat.prototype.Cp1 = '';
mycat = new Cat();
o = {};
// EDITED: using console.dir now instead of console.log
console.dir(mycat);
console.dir(o);
constructor
est une propriété [[DontEnum]] prédéfinie de l'objet pointé par la propriété prototype
d'un objet fonction et désignera initialement l'objet fonction lui-même.
__proto__
est équivalent à la propriété interne [[Prototype]] d'un objet, c'est-à-dire son prototype réel.
Lorsque vous créez un objet avec l'opérateur new
, sa propriété interne [[Prototype]] sera définie sur l'objet pointé par la propriété prototype
de la fonction constructeur.
Cela signifie que .constructor
sera évalué à .__proto__.constructor
, c'est-à-dire la fonction constructeur utilisée pour créer l'objet et, comme nous l'avons appris, la propriété protoype
de cette fonction a été utilisée pour définir le [[Prototype]] de l'objet.
Il s'ensuit que .constructor.prototype.constructor
est identique à .constructor
(tant que ces propriétés n'ont pas été remplacées); voir ici pour une explication plus détaillée.
Si __proto__
est disponible, vous pouvez parcourir la chaîne de prototypes de l’objet. ECMAScript3 ne dispose d'aucun moyen pour cela, car JavaScript n'a pas été conçu pour les hiérarchies d'héritage profondes.
L'héritage prototypal en JavaScript est basé sur la propriété __proto__
, en ce sens que chaque objet hérite du contenu de l'objet référencé par sa propriété __proto__
.
La propriété prototype
est spéciale uniquement pour les objets Function
et uniquement lorsque l'opérateur new
est utilisé pour appeler un constructeur Function
. Dans ce cas, le __proto__
de l'objet créé sera défini sur Function.prototype
du constructeur.
Cela signifie que l'ajout à Function.prototype
reflètera automatiquement tous les objets dont __proto__
fait référence à Function.prototype
.
Remplacer le Function.prototype
du constructeur par un autre objet pas mettra à jour la propriété __proto__
pour tout objet existant.
Notez que la propriété __proto__
ne doit pas être accédée directement, Object.getPrototypeOf (object) devrait être utilisé à la place.
Pour répondre à la première question, j'ai créé un diagramme sur mesure de références __proto__
et prototype
. Malheureusement, stackoverflow ne me permet pas d'ajouter l'image avec "moins de 10 réputation". Peut-être une autre fois.
[Edit] La figure utilise [[Prototype]]
au lieu de __proto__
car c'est ainsi que la spécification ECMAScript fait référence à des objets internes. J'espère que vous pouvez tout comprendre.
Voici quelques astuces pour vous aider à comprendre la figure:
red = JavaScript Function constructor and its prototype
Violet = JavaScript Object constructor and its prototype
green = user-created objects
(first created using Object constructor or object literal {},
second using user-defined constructor function)
blue = user-defined function and its prototype
(when you create a function, two objects are created in memory:
the function and its prototype)
Notez que la propriété constructor
n’existe pas dans les objets créés, mais qu’elle est héritée du prototype.
Object
est Eve et Function
est Adam, Adam (Function
) utilise son os (Function.prototype
) pour créer Eve (Object
). Alors qui a créé Adam (Function
)? - L'inventeur du langage JavaScript :-).
Selon la réponse d'Utsaina, je souhaite ajouter plus d'informations utiles.
La chose la plus surprenante pour moi a été de découvrir que
Object.__proto__
pointe surFunction.prototype
, au lieu deObject.prototype
, mais je suis bien sûr, il y a une bonne raison à cela :-)
CA ne devrait pas être. Object.__proto__
NE DOIT PAS pointer sur Object.prototype
. Au lieu de cela, l'instance de Object
o
, o.__proto__
doit pointer sur Object.prototype
.
(Pardonnez-moi d'utiliser les termes class
et instance
en JavaScript, mais vous le savez :-)
Je pense que la classe Object
elle-même est une instance de Function
, c'est pourquoi Object.__proto__ === Function.prototype
. Par conséquent: Object
est Eve et Function
est Adam, Adam (Function
) utilise son os (Function.prototype
) pour créer Eve (Object
).
De plus, même la classe Function
elle-même est une instance de Function
elle-même, c'est-à-dire Function.__proto__ === Function.prototype
, c'est aussi pourquoi Function === Function.constructor
De plus, la classe régulière Cat
est une instance de Function
, qui est Cat.__proto__ === Function.prototype
.
La raison de ce qui précède est que, lorsque nous créons une classe en JavaScript, nous ne faisons que créer une fonction, qui devrait être une instance de Function
. Object
et Function
sont juste spéciaux, mais ce sont toujours des classes, alors que Cat
est une classe ordinaire.
En guise de facteur, dans le moteur JavaScript de Google Chrome, les 4 suivants:
Function.prototype
Function.__proto__
Object.__proto__
Cat.__proto__
Ils sont tous ===
(absolument égaux) aux 3 autres, et leur valeur est function Empty() {}
> Function.prototype
function Empty() {}
> Function.__proto__
function Empty() {}
> Object.__proto__
function Empty() {}
> Cat.__proto__
function Empty() {}
> Function.prototype === Function.__proto__
true
> Function.__proto__ === Object.__proto__
true
> Object.__proto__ === Cat.__proto__
true
D'ACCORD. Alors qui crée la function Empty() {}
(Function.prototype
) spéciale? Penses-y :-)
Je ne sais vraiment pas pourquoi les gens ne vous ont pas corrigé au sujet du problème réel dans votre compréhension.
Cela rendrait beaucoup plus facile pour vous de repérer le problème
Voyons ce qui se passe:
var newtoy = new Gadget("webcam", "black")
newtoy
.constructor //newtoy's constructor function is newtoy ( the function itself)
.prototype // the function has a prototype property.( all functions has)
.constructor // constructor here is a **property** (why ? becuase you just did `prototype.constructor`... see the dot ? ) ! it is not(!) the constructor function !!! this is where your mess begins. it points back to the constructor function itself ( newtoy function)
.prototype // so again we are at line 3 of this code snippet
.constructor //same as line 4 ...
.prototype
rating = 3
Génial, alors regardons ce __proto__
Avant cela, rappelez-vous 2 choses concernant __proto__
:
Lorsque vous créez un objet avec l'opérateur new
, sa propriété interne [[Prototype]]
/proto__
est définie sur la propriété prototype
(1) de son constructor function
ou "créateur" si vous le souhaitez.
Codé en dur dans JS -: Object.prototype.__proto__
est null
.
Appelons ces deux points "bill
"
newtoy
.__proto__ // When `newtoy` was created , Js put __proto__'s value equal to the value of the cunstructor's prototype value. which is `Gadget.prototype`.
.__proto__ // Ok so now our starting point is `Gadget.prototype`. so regarding "bill" who is the constructor function now? watch out !! it's a simple object ! a regular object ! prototype is a regular object!! so who is the constructor function of that object ? Right , it's the `function Object(){...}`. Ok .( continuing "bill" ) does it has a `prototype` property ? sure. all function has. it's `Object.prototype`. just remember that when Gadget.prototype was created , it's internal `__proto__` was refered to `Object.prototype` becuase as "bill" says :"..will be set to the `prototype` property of its `constructor function`"
.__proto__ // Ok so now our satrting point is `Object.prototype`. STOP. read bullet 2.Object.prototype.__proto__ is null by definition. when Object.prototype ( as an object) was created , they SET THE __PROTO__ AS NULL HARDCODED
Meilleur?
Chaque fonction crée son prototype . Et lorsque nous créons un objet à l'aide de son constructeur, la propriété_PROTO_de mon objet commence à pointer vers le prototype de cette fonction.
Si tous ces chiffres sont accablants, examinons ce que signifient les propriétés.
STH.prototype
Lors de la création d'une nouvelle fonction, un objet vide est créé en parallèle et lié à la fonction avec la chaîne [[Prototype]]
. Pour accéder à cet objet, nous utilisons la propriété prototype
de la fonction.
function Gadget() {}
// in background, new object has been created
// we can access it with Gadget.prototype
// it looks somewhat like {constructor: Gadget}
N'oubliez pas que la propriété prototype
n'est disponible que pour les fonctions.
L'objet prototype mentionné ci-dessus n'a aucune propriété sauf une - constructor
. Cette propriété représente une fonction qui a créé l'objet prototype.
var toy = new Gadget();
Lors de la création de la fonction Gadget
, nous avons également créé un objet comme {constructor: Gadget}
- qui n’a rien à voir avec Gadget.prototype
. Comme constructor
fait référence à une fonction qui a créé un prototype d'objet, toy.constructor
représente la fonction Gadget
. Nous écrivons toy.constructor.prototype
et nous obtenons à nouveau {constructor: Gadget}
.
Il existe donc un cercle vicieux: vous pouvez utiliser toy.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype
et ce sera toujours Gadget.prototype
.
toy
.constructor // Gadget
.prototype // {constructor: Gadget}
.constructor // Gadget
.prototype // {constructor: Gadget}
// ...
Bien que prototype
soit une propriété spécifique aux fonctions, __proto__
est disponible pour tous les objets, comme il est décrit dans Object.prototype
. Cela fait référence au prototype d'une fonction pouvant créer un objet.
[].__proto__ === Array.prototype
// true
({}).__proto === Object.prototype
// true
Ici, toy.__proto__
est Gadget.prototype
. Comme Gadget.prototype
est un objet ({}
) et que les objets sont créés avec la fonction Object
(voir l'exemple ci-dessus), nous obtenons Object.prototype
. C'est l'objet supérieur en JavaScript et son __proto__
ne peut indiquer que null
.
toy
.__proto__ // Gadget.prototype (object looking like {constructor: Gadget})
.__proto__ // Object.prototype (topmost object in JS)
.__proto__ // null - Object.prototype is the end of any chain