Corriger la chaîne prototype pour la fonction

Quelle est la sortie correcte (c'est-à-dire correcte par la norme ECMA) du programme suivant?

function nl(x) { document.write(x + "<br>"); } nl(Function.prototype); nl(Function.prototype.prototype); nl(Function.prototype.prototype == Object.prototype); nl(Function.prototype.prototype.prototype); 

Chrome et IE6 s'accordent à dire:

 function Empty() {} null for Chrome / undefined for IE6 false 

Et ensuite s'écraser.

Sorties Mozilla:

 function () { } [object Object] false undefined 

Est-ce que l'une ou l'autre est correcte? Il semble que le Mozilla fonctionne mieux, mais que la meilleure sortie est

 function () { } [object Object] true undefined 

Ce que vous faites ici n'est pas vraiment la marche de la chaîne prototype – cette question pourrait vous aider à comprendre ce qui se passe réellement. Je n'ai pas pris la peine de vérifier la spécification ECMA, mais voici mon point de vue:

  • La fonction est le constructeur des objets fonctionnels

  • Function.prototype est le prototype à partir duquel tous les objets de fonctions héritent – il peut contenir des propriétés comme appel et appliquer qui sont communes à toutes les instances de fonction ; Les implémentations que vous avez vérifiées sont cohérentes dans la mesure où elles sont implémentées comme un objet de fonction lui-même (comme certains le soulignent, la spécification ECMA requiert cela)

  • Leprojet de fonction.protéotype n'a pas beaucoup de sens, mais comme fonction.protéotype est implémenté comme un objet fonction (qui pourrait être utilisé comme constructeur), il devrait au moins exister; Les objets qui sont créés à l'aide de Function.prototype en tant que constructeur hériteraient de leurs propriétés – mais comme il ne devrait pas y avoir de raison de faire quelque chose d'insensé comme celui-ci, le définir comme nul , indéfini ou un objet vide est raisonnable

  • Leprojet de fonction.prototype.prototype.d'une vraisemblance sera indéfini : comme nous l'avons déjà vu, Function.prototype.prototype devrait être quelque chose sans propriétés ( nul , indéfini ou un objet vide) et n'est pas définitivement un objet fonctionnel; Par conséquent, sa propriété prototype doit être indéfinie ou peut même lancer une erreur en essayant d'accéder

J'espère que cela t'aides 😉

Fonction.prototype

À partir de la spécification de langue ECMAScript :

15.3.3.1 Function.prototype

La valeur initiale de Function.prototype est l'objet prototype fonction (section 15.3.4).

15.3.4 Propriétés de l'objet Prototype de fonction

L'objet prototype Fonction est lui-même un objet Fonction (son [[Classe]] est "Fonction") qui, lorsqu'il est invoqué, accepte tout argument et renvoie indéfini. La valeur de la propriété [[Prototype]] interne de l'objet prototype Fonction est l'objet prototype Object (section 15.3.2.1).

C'est une fonction avec un "corps vide"; Si elle est invoquée, elle renvoie simplement indéfinie. L'objet prototype Function n'a pas de propriété valueOf propre; Cependant, il hérite de la propriété valueOf à partir de Object Object prototype.

Je reçois cette sortie:

  • Opera: function () {[code natif]}
  • Chrome: fonction vide () {}
  • IE7: prototype de fonction () {[code natif]}
  • FF3: function () {}

Chrome et IE7 ont nommé leurs fonctions, Opera et IE7 vous indiquent qu'il ne révélera pas la mise en œuvre. Ils sont tous d'accord sur ceci:

 nl(typeof Function.prototype); //function 

Comparez ceci à:

 nl(typeof Object.prototype); //object nl(typeof Array.prototype); //object nl(typeof String.prototype); // object 

Fonction.prototype.prototype

Je ne suis pas défini sur Opera et IE7, null depuis Chrome et [object Object] depuis FF3. Qui a raison? Puisque "l'objet prototype de la fonction est lui-même un objet fonction" , ne devrait-il pas être une référence circulaire? Pour éviter la référence circulaire, ils ont choisi différentes manières. Je ne sais pas s'il existe une norme pour cela ou si cela dépend de la mise en œuvre, mais je pense qu'un objet est juste. Btw, voici la différence entre le prototype interne [] et le prototype public en action, comme vous l'avez demandé dans une question antérieure!

Function.prototype.prototype == Object.prototype

Ceci est faux car ce n'est pas le même objet. Voir au dessus.

Propriété.prototype.prototype.prototype

Seul FF vous donnera une réponse en raison de leur implémentation de Function.prototype.prototype renvoie un objet.

Je suis d'accord que votre résultat proposé ressemble plus à la logique.

Ils sont d'accord sur ceci:

 nl(Object.prototype); // [object Object] nl(Object.prototype.prototype); // undefined 

Pour répondre directement à votre question: Mozilla a raison. Non seulement parce que Brendan Eich travaille pour Mozilla, mais parce que c'est le seul bon moyen de le faire. Examinons les détails:

  • Chaque constructeur est une fonction.
  • Chaque fonction possède une propriété prototype à utiliser pour construire des objets.
  • Le prototype est un objet (un dictionnaire). Les objets individuels délèguent les méthodes / propriétés à leurs prototypes respectifs.
  • Dans le cas d'une fonction, l'objet prototype est spécial – il met en œuvre des méthodes et des propriétés spécifiques à la fonction. Le type / classe de cet objet n'est pas défini et n'est pas directement disponible.
  • Cet objet prototype ne peut pas être Object ni Object.prototype .

Permettez-moi de préciser la dernière déclaration. Si c'est faux, nous pouvons recréer une fonction dans le code utilisateur comme ça:

 // we re-creating the function! // our function constructor var Fun = function(){ /*...*/ }; // let's chain the prototype Fun.prototype = new Object(); // do we have a function now? let's fund out var fun = new Fun(); console.log(fun.length); // undefined fun.call(null); // fail fun.apply({}, [1, 2, 3]); // fail // nope 

Nous pouvons observer que new Object() ne définit pas de nouvelles méthodes ni propriétés et peut essayer d'utiliser Object.prototype directement avec le même résultat.

Résumé: le prototype de la fonction n'est pas Object ni Object.prototype . C'est un objet très spécial. C'est une raison supplémentaire pour laquelle nous ne pouvons pas recréer une fonction dans le code utilisateur.

EDIT: pour plus de détails sur les prototypes, regardez cette réponse .

Je sais que ce post est un peu vieux, mais j'ai cherché sur le net des informations sur ce sujet et pensé que je publierais ce que j'ai trouvé. La propriété prototype est destinée aux fonctions constructeur. Il vous permet d'attribuer l'objet prototype des objets que vous allez créer avec le nouveau mot-clé.

Chaque objet en JavaScript a un objet prototype, mais de nombreuses implémentations ne vous donnent pas directement accès ou vous permettent de le définir après la création de l'objet. Dans FireFox, vous pouvez accéder à cet objet via la propriété " __proto__ ".

Ci-dessous, j'ai une version de votre code en utilisant la propriété " __proto__ ". La section sur la chaîne de prototypes fonction correspond à ce que vous pensiez qu'il aurait dû être.

 function nl(z) { document.write(z + "<br>"); } x = {}; nl(x["__proto__"]); nl(x["__proto__"] === Object.prototype); nl(""); nl(nl.prototype.constructor); nl(nl["__proto__"].constructor); nl(nl["__proto__"] === nl.prototype); nl(""); nl(nl["__proto__"]); nl(nl["__proto__"] === Function.prototype); nl(nl["__proto__"]["__proto__"] === Object.prototype); nl(nl["__proto__"]["__proto__"]["__proto__"]); nl(""); nl(Function["__proto__"]); nl(Function["__proto__"]["__proto__"]); nl(Function["__proto__"]["__proto__"] === Object.prototype); nl(Function["__proto__"]["__proto__"]["__proto__"]); 

La sortie dans FireFox est:

 [object Object] true function nl(z) { document.write(z + " "); } function Function() { [native code] } false function () { } true true null function () { } [object Object] true null