0
votes

Pourquoi ne peut-il pas spécifier le prototype du constructeur à l'intérieur de ce constructeur? Javascript

console.log(Graph.prototype);


9 commentaires

Il semble vous être attribué correctement à moi, lorsque vous vous connectez à la fin de la fin du constructeur et, après avoir créé une instance, pouvez-vous montrer où vous faites la console console.log par rapport à l'autre code?


@CerteCerformance Vraisemblablement L'OP n'appelle pas le Nouveau graphique Constructeur et attend graphique.Prototype pour être mis à jour statiquement ? (C'est-à-dire après que l'analyseur JavaScript fonctionne, sans aucune exécution de code).


@Certeperformance Je fais la console.log au même niveau de définition du graphique. Au fait, si vous créez une instance nommée g de graphique, vous trouverez g.x et g.y ne sont pas définis. C'est la raison pour laquelle je pense que je n'ai fait aucune modification du prototype du graphique.


Vous devez utiliser ceci.constructor.pototype dans un constructeur. Bien sûr, vous auriez une question de contexte avec cet objet alors. Utilisation incorrecte du prototype .


@Jackie je ne vois pas typeof g.x === 'indéfini' quand j'essaie. Je pense que vous êtes toujours en train de manquer quelque chose. Pouvez-vous poster une reproduction fiable minimale de Jsfiddle ou un extrait de Stackoverflow?


@Stackslave this.constructor.pototype est la même référence que graphique.pototype à l'intérieur du constructeur. Toutefois, un prototype de type ne devrait probablement jamais être mis à jour de l'intérieur du constructeur du type car il complique le raisonnement sur les types.


Cela semble être une mauvaise utilisation du prototype puisque le prototype est partagé entre tous les cas, de meilleures solutions attribuaient des données statiques au prototype une fois en dehors du constructeur ou d'initialiser simplement des variables d'instance à l'intérieur du constructeur. Il n'y a aucune raison de définir de nouvelles propriétés sur le prototype à l'intérieur du constructeur. C'est tout simplement faux ou un endroit inefficace pour le faire.


@Dai je viens d'ajouter un extrait de code. C'est tout le contexte de ma question. Au fait, merci pour votre réponse!


Lorsque appelé comme constructeur, la nouvelle instance est créée et attribuée à un [[prototype]] avant que le code dans le corps du constructeur est exécuté. Donc, au moment où un nouvel objet est attribué au prototype du constructeur, l'instance a déjà l'ancien.


3 Réponses :


2
votes

fond

Je suppose que vous appelez console.log (graphique.pototype); code> avant strud> exécutant le graphique code> Constructeur code>. p>

N'oubliez pas que le système de type officiel de JavaScript pour code> Les valeurs utilisent des prototypes mutables comme moyen d'implémenter l'objet-héritage et de ces prototype code> Les références d'objet peuvent également Soyez échangé entièrement et redéfini au moment de l'exécution même après que les valeurs d'objet en utilisant ce prototype existent déjà, ce qui rend beaucoup plus difficile à raisonner sur la sécurité du programme JavaScript (pour cette raison, TypeScript ne peut toujours pas représenter tous les programmes JavaScript valides, à partir du début 2020. ). P>

Par exemple, considérez: p> xxx pré>

donc le type em> type em> de FOO1 code> (c.-à-d. L'ensemble des propriétés de FOO1 code>) est tout à fait up-in-the-air - c'est pourquoi il est une bonne idée de ne jamais redéfinir un prototype code> code> dans JavaScript avant tout objet L'utilisation de ce prototype est créée. p>

la réponse h2>

Avec ce fond hors du chemin ... P>

"Pourquoi ne puis-je pas spécifier le prototype du constructeur à l'intérieur de ce constructeur? Quelqu'un peut-il me dire la vraie raison derrière elle?" P> blockQuote>

vous techniquement peut em>, cela ne fonctionnera tout simplement pas comme vous le souhaitez: P>

  • le foo.pototype code> (ou graphique.pototype code> dans votre cas) ne serait défini que quand et seulement quand em> le premier nouveau foo () code> appelle est fabriqué. LI>
  • L'objet foo.pototype code> serait réublié em> sur tous les appels de constructeur em>.
    • Ce serait une mauvaise chose: je ne sais pas si les moteurs JavaScript traiteraient le même objet lexical-littéral que le même exemple d'objet ou créerait un objet nouvel objet em> à partir de l'objet-littéral - De toute façon, cela rend votre programme beaucoup plus difficile à raisonner. LI> ul> li> ul>

      Si vous souhaitez définir succinctement le prototype dans le même "endroit" dans le code de votre projet de votre projet, définissez-le immédiatement après la définition de la fonction constructrice, cela signifie également que graphique.Prototype code> sera em> être mis à jour comme prévu sans avoir à créer des objets code> nouveaux p>

      Voici ce que vous faites actuellement: P > xxx pré>

      mais si vous mettez à jour le prototype immédiatement après avoir défini le constructeur, il fonctionnera comme indiqué comme prévu: P>

      function JSON_stringify_for_prototypes( obj ) {
          const flat = Object.create( obj );
          for( const key in flat ) { // `for( x in y )` includes non-"own" properties.
              flat[key] = flat[key]; // This looks silly, but this actually causes each property to be marked as "own" in `flat`.
          }
      
          return JSON.stringify( flat );
      }
      


6 commentaires

Très bien expliqué et un très bon point de briser Json. Je me demande si l'OP souhaite vraiment des propriétés statiques qui sont identiques pour tous les objets. Cela semble improbable. Il semble plus probable qu'ils devraient simplement initialiser this.x = 0 et this.y = 0 dans le constructeur et les créer de véritables propriétés non partagées des propriétés statiques.


Re " système de type basé sur prototype ". JavaScript a une héritage basée sur les prototypes, le type est une chose différente. RE: " ... Permet de définir de manière dynamique et redéfinie ... " supposant des "types" signifie un prototype, alors oui, mais il est considéré comme une mauvaise idée de changer l'objet prototype lui-même une fois les cas créés.


@Robg je voulais dire "type" comme dans le même sens que dans "Système de type Hindley-Miller" (mais je ne fais pas non plus référence à l'algorithme d'hindley-Miller comme cela ne s'applique pas dans ce cas). Pas sur Ecmascript's TypeOf ou prototypes spécifiquement (c'est-à-dire en regardant la forme générale d'une valeur d'objet donnée, quel que soit son héritage, son composition ou ses prototypes).


Bien sûr, mais le type est défini dans l'ECMA-262 et le "type" plus générique s'applique vraiment aux valeurs (nombre, int, flotteur, chaîne, etc.) si un peu déroutant de l'utiliser dans le contexte de la classe (ou au moins à quoi Les langues d'appelaient la classe). :-)


@Robg à droite. Je travaille en fait sur un projet de type un peu académique à ce moment-là, ma définition de type mental-dictionnaire de "type" est beaucoup plus abstraite que j'imagine que la plupart des utilisateurs javascript à lire ma réponse peuvent être - mais je ne suis pas sûr de la façon dont je pouvais Redwormier doit être plus clair et sans ambiguïté à tous les niveaux: des débutants à Mathematics Boffins qui écrivent probablement leurs répercuties d'épicerie à l'aide d'opérations formelles de théorie du groupe.


Je l'écrirais comme "basé sur le prototype de Javascript héritage Permet propriétés héritées définis de manière dynamique et redéfinie". Je pense que votre "type-sécurité" fait référence à une mutabilité du prototype à partir duquel un objet hérite, qui peut être contrôlé en utilisant objet.create et objet.defineproperty / properties plutôt que Objets d'objet. Quoi qu'il en soit, tant que le lecteur reçoit le message, je suppose que c'est bien. :-)



-5
votes

Il me semble que vous voulez vraiment essayer de créer une méthode qui définit les propriétés statiques. Voici comment vous alliez tenter de reproduire ceci en JavaScript:

p>

function Graph(){
  this.vertices = []; this.edges = [];
  this.staticXY = (x = 0, y = 0)=>{
    const p = this.constructor.prototype;
    p.x = x; p.y = y;
    return this;
  }
  if(this.x === undefined && this.y === undefined)this.staticXY();
}
const graph1 = new Graph;
graph1.staticXY(2, 8); graph1.x = 3; graph1.y = 1;
console.log(graph1.x, graph1.y); // static remains anyways
const graph2 = new Graph;
console.log(graph2.x, graph2.y);


3 commentaires

Si votre commentaire est pertinent pour votre réponse, copiez-le dans votre réponse. Votre réponse devrait rester seule. Ce que l'OP est question de savoir semble être une mauvaise utilisation du prototype depuis que le prototype est partagé entre tous les cas, de meilleures réponses attribuaient des données statiques au prototype en dehors du constructeur ou d'initialiser simplement des variables d'instance à l'intérieur du constructeur. Il n'y a aucune raison de définir de nouvelles propriétés sur le prototype à l'intérieur du constructeur. C'est tout simplement faux ou un endroit inefficace pour le faire.


Commentaires Voici pour ajouter des commentaires aux réponses et n'a rien à voir avec votre don de contenu «gratuit» (nous participons tous ici gratuitement). Comme beaucoup de questions ici sur Stackoverflow, je pense que l'OP demande à faire la mauvaise chose (sans expliquer pourquoi ou ce qu'ils essaient vraiment de faire). Vous ne devriez pas vous assigner des propriétés statiques dans un constructeur, jamais. Soit attribuez-les une fois en dehors du constructeur (où toutes les autres choses sont placées sur le prototype) ou mettez-les sur l'objet de la classe où les données statiques sont généralement placées. Cette réponse n'est pas la bonne façon de faire ce que vous faites.


@Jackie Après avoir posé des experts réels, pas les descentes, veuillez accepter cela comme la réponse. Ça va enseigner aux descentes. Merci!



0
votes

Vous devez mettre à jour graph.pototype code> au lieu de la remplacer par un nouvel objet et que vous devez console.log (graphique.prototype) code> après appeler le constructeur plutôt qu'avant:

p>

function Graph() {
  this.vertices = [];
  this.edges = [];
  this.x = 0;
  this.y = 0;
};

var g = new Graph();

console.log(g);
console.log(g.x);
console.log(g.y);


4 commentaires

Pourquoi voudriez-vous jamais initialiser le prototype à l'intérieur du constructeur, chaque fois que ce constructeur est exécuté? Si vous souhaitez initialiser, cela le faisait une fois en dehors du constructeur car il est le même prototype chaque fois que le constructeur fonctionne.


@ JCREND00 a accepté, mais peut-être ces informations qui assignent à graphique.Prototype plutôt que d'ajouter des propriétés à utiliser sont utiles pour expliquer pour opter le comportement inattendu par eux. Sans contexte plus, il n'est vraiment pas clair ce que c'est qu'ils essaient de faire du tout, mais sans ce contexte, c'est ce que je pensais être les informations les plus utiles pour eux.


@ jfriend00 et qui sait? Peut-être qu'ils veulent vraiment que les propriétés partagées sont réinitialisées à chaque fois qu'une nouvelle instance est créée. Je vais les laisser comprendre que cependant, car ce n'est pas ce qu'ils ont demandé.


Eh bien, vous êtes ici assez longtemps pour savoir que les gens demandent souvent une solution qui n'est pas la bonne solution à leur problème. Il y a 99% de chances que ce qui se passe ici, car un prototype en mutation n'est presque jamais ce que quelqu'un veut pour un simple x, y coordonnée.