11
votes

Copier JavaScript Getters / Setters vers un autre objet prototype

// Base class
var Base = function() {
    this._value = 'base';
};
Base.prototype = {
    constructor: Base,
    // By function
    getValue: function() {
        return this._value;
    },
    // By getter
    get value() {
        return this._value;
    }
};

// Sub class extends Base
var Sub = function() {
    this._value = 'sub';
};
Sub.prototype = {
    constructor: Sub
};
// Pass over methods
Sub.prototype.getValue = Base.prototype.getValue;
Sub.prototype.value = Base.prototype.value;

// ---

var mySub = new Sub();
alert(mySub.getValue()); // Returns 'sub'
alert(mySub.value);      // Returns 'undefined'
At first glance it seems that mySub.value should return the same as mySub.getValue(), but as you can see it instead returns undefined. Obviously the getter is not finding the parent scope as the Sub instance (mySub), but rather a non-existent Base instance.Is there any way around this other than having to assign the same getters onto the new prototype?

2 commentaires

Je sais que cela ne répond pas à votre question ... Mais pourquoi avez-vous même besoin de la getter? Cette complexité inutile n'est-elle pas?


@Michael bien dans cet exemple, évidemment, il est inutile, je viens de l'écrire pour donner une idée claire du problème que je faisais face. Dans mon application actuelle, lors de l'obtention / de la définition de certaines propriétés, j'ai besoin de déclencher d'autres fonctions et du code.


4 Réponses :


6
votes

Je pense que cela fonctionnerait si vous avez attribué

var Sub = function() {}
Sub.Extend(Base)


4 commentaires

Cela ne m'a jamais eu pour moi de faire héritage comme ça. Quelle belle solution élégante!


Merci :-) laissez-moi trouver la source (je ne l'ai sûrement pas écrit ...)


Woah! Cela mérite une certaine attention. Grande solution.


Le seul problème avec cette forme d'héritage est que ce n'est pas un héritage, c'est le fatalisme. Toutes les classes de base sont initialisées ( nouvelle superclasse () ) sur la durée de définition (lorsque la bibliothèque est chargée, laquelle sub.extend (base) ) au lieu de l'heure d'exécution (lorsque la La bibliothèque est utilisée comme neuf sous () ). Exemple: sub1.extend (base1) et sub2.extend (base2) mais base1 a besoin nouveau Sub2 () et base2 nécessite nouveau sub1 () . Non, il n'y a pas de cycle de cétantanément si vous n'exécutant que dans l'initialisation une fois.



11
votes
Sub.prototype.__defineGetter__('value', Base.prototype.__lookupGetter__('value'));
Try that.

2 commentaires

DefineGetter est non standard et n'est pas dans la norme ECMA-262. Y a-t-il une solution alternative de faire cela?


@Tylercrompton: objet.defineProperty (Sub, 'valeur', objet.getownPropertydescr iptor (base, «valeur»));



2
votes

en plus de réponse de Alex MCP , vous pouvez ajouter de nouveaux getters / setters à SUB après le prolonger : xxx

et ajouter à Tylermwashburns Réponse: vous pouvez étendre le prototype de fonction pour que: xxx


0 commentaires

11
votes

Une solution plus moderne consiste à utiliser le objet.defineproperty code> car il permet de gérer les getters et les setters sans les casser.

Un seul problème est qu'il faut un objet de descripteur, donc au lieu de En faisant manuellement une, utilisez la fonction objet.getownpropertyDescriptor code> pour l'obtenir pour vous. P>

var BazValue = Object.getOwnPropertyDescriptor(Base.prototype,'value');

Object.defineProperty(Sub.prototype, 'value', BazValue);


2 commentaires

Cela m'a aidé à Polyfill Mouseevent.x : Object.defineProperty (Mouseevent.Prototype, "X", Object.getownPropertyDescriptor (Mouseevent.Prototype, "ClientX")) .


Cela devrait être la réponse acceptée aujourd'hui. Toutefois DefineProperty / getownPropertyDescriptor est de ECMAScript 5.1 qui a été défini en juin 2011, un mois après La réponse actuellement acceptée