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:
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:
prototype
à utiliser pour construire des objets. 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