J'ai le modèle d'héritage simple suivant et j'aimerais savoir s'il est correct d'appeler des méthodes comme je le fais depuis la fonction constructeur (en gros, en utilisant this au lieu de "super prototype".

Classe parent, Pet

function Pet(name) {
  this.name = name;
  this.nickname = name;

  this.adopt();
}

Pet.prototype.adopt = function() {
  this.nickname = 'Cutty ' + this.name;
}

Pet.prototype.release = function() {
  this.nickname = null;
}

Pet.prototype.cuddle = function() {
  console.log(this.name + ' is happy');
}

Sous-classe, Lion

function Lion(name) {
  Pet.prototype.constructor.apply(this, arguments); // super(name)
  this.cuddle();
  this.release();
}
Lion.inherits(Pet);

Lion.prototype.adopt = function() {
  // DTTAH
}

Lion.prototype.release = function() {
  Pet.prototype.release.call(this);
  console.log('Thanks for releasing ' + this.name);
}

inherits helper (les polyfills sont mauvais je sais)

Function.prototype.inherits = function(Parent) {
  function ProtoCopy() {}
  ProtoCopy.prototype = Parent.prototype;

  this.prototype = new ProtoCopy();
  this.prototype.constructor = this;
}

Mes animaux sont instanciés comme ça var lion = new Lion('Simba')

Dans le constructeur Lion,
Puis-je continuer à utiliser this lors de l'appel de méthodes de classe sub / parent? Ou devrais-je utiliser directement les méthodes du prototype parent? (comme un pseudo appel à super() ou à release())

Les raisons pour lesquelles je demande sont:

  • this substitution à l'exécution
  • constructor propriété pas toujours ce que nous pensons (d'après ce que j'ai lu ici et là)

Je ne sais pas comment ces choses peuvent influencer l'objet résultant.

Merci pour votre illumination!

3
Jordan 20 juil. 2015 à 22:03

2 réponses

Meilleure réponse

Quelle est la différence entre l'utilisation de this.fn() et MyClass.prototype.fn.call(this) dans une fonction constructeur?

Ce n'est pas spécifique aux fonctions constructeur, c'est la même chose dans toutes les fonctions (méthodes) qui sont appelées sur des instances.

En effet, il n'y a pas beaucoup de différence en dehors du nombre de caractères lorsque this.fn === MyClass.prototype.fn, et ils se comporteraient exactement de la même manière. Cependant, cette hypothèse n'est pas toujours vraie - this peut ne pas hériter directement de MyClass.prototype, mais plutôt être une instance de sous-classe , et cette sous-classe peut avoir écrasée la méthode this.fn.

Alors, lequel est correct? Les deux, en fait. Si vous connaissez la différence, vous pouvez choisir celui qui convient à votre cas. D'autres langages ont des attentes par défaut différentes ici, voir aussi pour appeler des méthodes statiques.

Notez que vous ne pouvez pas remplacer la référence de classe par this.constructor, qui serait également écrasée. Dans une configuration raisonnable 1 , this.fn() serait toujours équivalent à this.constructor.prototype.fn.call(this).

Ceci est similaire à la raison pour laquelle les super appels doivent explicitement référencer la super classe et ne pas dépendre des propriétés de l'instance (telles que this.constructor, this.super ou quelque chose de similaire).

1: Où this.fn est une méthode habituelle héritée du prototype, pas une méthode propre à une instance, et où chaque prototype a le .constructor pointant vers le constructeur respectif dont il est .prototype.

1
Community 23 mai 2017 à 12:21

Pour simplifier le problème, considérez le code suivant dans ES6:

class Pet {
  constructor (name) {
    this.name = name;
    this.talk();
  }
  talk () {
    console.log('My name is ' + this.name);
  }
}

class Lion extends Pet {
  constructor (name) {
    super(name);
  }
  talk () {
    super.talk();
    console.log('I am a lion.');
  }
}

Serait équivalent à:

function Pet (name) {
  this.name = name;
  this.talk();
}
Pet.prototype.talk = function () {
  console.log('My name is ' + this.name);
};

function Lion (name) {
  Pet.call(this, name);
}

// inheritance:
Lion.prototype = Object.create(Pet.prototype);
Lion.prototype.constructor = Lion;

// override .talk
Lion.prototype.talk = function () {
  Pet.prototype.talk.call(this);
  console.log('I am a lion');
}

Exécution des journaux new Lion('Bobby'):

My name is Bobby
I am a lion

Lectures complémentaires: http://eli.thegreenplace.net/ 2013/10/22 / héritage-classique-en-javascript-es5

1
deleted user 21 juil. 2015 à 01:10