87 votes

Comment définir un setter/getter sur un prototype ?

EDIT Oct. 2016 : Veuillez noter que cette question a été posée en 2012. Chaque mois ou presque, quelqu'un ajoute une nouvelle réponse ou un commentaire qui réfute une réponse, mais cela n'a pas vraiment de sens de le faire car la question est probablement dépassée (rappelez-vous, c'était pour Gnome Javascript pour écrire des extensions gnome-shell, pas des trucs de navigateur, ce qui est assez spécifique).

Suivant ma question précédente sur la façon de faire des sous-classes en Javascript, je fais une sous-classe d'une super-classe comme ceci :

function inherits(Child,Parent) {
    var Tmp = function {};
    Tmp.prototype = Parent.prototype;
    Child.prototype = new Tmp();
    Child.prototype.constructor = Child;
}
/* Define subclass */
function Subclass() {
    Superclass.apply(this,arguments);
    /* other initialisation */
}
/* Set up inheritance */
inherits(Subclass,Superclass);
/* Add other methods */
Subclass.prototype.method1 = function ... // and so on.

Ma question est la suivante , comment définir un setter/getter sur le prototype avec cette syntaxe ?

J'avais l'habitude de le faire :

Subclass.prototype = {
    __proto__: Superclass.prototype,
    /* other methods here ... */

    get myProperty() {
        // code.
    }
}

Mais il est évident que ce qui suit ne fonctionnera pas :

Subclass.prototype.get myProperty() { /* code */ }

J'utilise GJS (GNOME Javascript), et le moteur est censé être plus ou moins le même que celui de Mozilla Spidermonkey. Mon code n'est pas destiné à un navigateur, donc tant qu'il est supporté par GJS (je suppose que cela signifie Spidermonkey ?), cela ne me dérange pas s'il n'est pas cross-compatible.

113voto

Bergi Points 104242

Utilisez Object.defineProperty() sur Subclass.prototype . Il existe également __defineGetter__ y __defineSetter__ disponibles sur certains navigateurs, mais ils sont dépréciés. Pour votre exemple, ce serait :

Object.defineProperty(Subclass.prototype, "myProperty", {
    get: function myProperty() {
        // code
    }
});

78voto

bfavaretto Points 46777

Utilisation d'une déclaration littérale d'objet (méthode la plus simple) :

var o = {
    a: 7,
    get b() {
        return this.a + 1;
    },
    set c(x) {
        this.a = x / 2
    }
};

Utilisation de Object.defineProperty (sur les navigateurs modernes qui prennent en charge ES5) :

Object.defineProperty(o, "myProperty", {
    get: function myProperty() {
        // code
    }
});

Ou en utilisant __defineGetter__ y __defineSetter__ ( DÉCRYPTÉ ) :

var d = Date.prototype;
d.__defineGetter__("year", function() { return this.getFullYear(); });
d.__defineSetter__("year", function(y) { this.setFullYear(y); });

43voto

Je pense que tu voulais faire comme ça :

function Unit() {
    this._data; // just temp value
}
Unit.prototype = {
    get accreation() {
        return this._data;
    },
    set accreation(value) {
        this._data = value
    },
}
Unit.prototype.edit = function(data) {
    this.accreation = data; // setting
    this.out();
};

Unit.prototype.out = function() {
    alert(this.accreation); // getting
};

var unit = new Unit();
unit.edit('setting and getting');

function Field() {
    // children
}

Field.prototype = Object.create(Unit.prototype);

Field.prototype.add = function(data) {
  this.accreation = data; // setting
    this.out();
}

var field1 = new Field();
field1.add('new value for getter&setter');

var field2 = new Field();
field2.out();// because field2 object has no setting

5voto

Mackraken Points 337

Pour définir les setters et getters "à l'intérieur du prototype de l'objet", vous devez faire quelque chose comme ceci :

Object.defineProperties(obj.__proto__, {"property_name": {get: getfn, set: setfn}})

Vous pouvez raccourcir cela avec une fonction d'utilité :

//creates get/set properties inside an object's proto
function prop (propname, getfn, setfn) {
    var obj = {};
    obj[propname] = { get: getfn, set: setfn };
    Object.defineProperties(this, obj);        
}

function Product () {
     this.name =  "Product";
     this.amount =  10;
     this.price =  1;
     this.discount =  0;
}

//how to use prop function
prop.apply(Product.prototype, ["total", function(){ return this.amount * this.price}]);

pr = new Product();
console.log(pr.total);

Ici, nous utilisons prop.apply pour définir le contexte Product.prototype comme "this" lorsque nous l'appelons.

Avec ce code, vous obtenez une propriété get/set dans le prototype de l'objet, et non dans l'instance, comme le demandait la question.

(Testé sur Firefox 42, Chrome 45)

4voto

Michael Horojanski Points 1567

Spécifier un getter ou un setter dans les constructeurs par la méthode Object.defineProperty(). Cette méthode prend trois arguments : le premier l'objet auquel ajouter la propriété, le deuxième est le nom de la propriété et le troisième est le le troisième est le descripteur de la propriété. Par exemple, nous pouvons définir le constructeur de notre objet personne comme suit :

var Employee = (function() {
    function EmployeeConstructor() {
        this.first = "";
        this.last = "";
        Object.defineProperty(
            this,
            "fullName", {
                get: function() {
                    return this.first + " " +
                        this.last;
                },
                set: function(value) {
                    var parts = value.toString().split(" ");
                    this.name = parts[0] || "";
                    this.last = parts[1] || "";
                }
            });
    }
    return
    EmployeeConstructor;
}());

L'utilisation de Object.defineProperty() donne plus de contrôle sur la définition de notre propriété. Par exemple, nous pouvons spécifier si la propriété que nous que nous décrivons peut être supprimée ou redéfinie dynamiquement, si sa valeur peut être modifiée, etc. et ainsi de suite.

Nous pouvons établir de telles contraintes en définissant les propriétés suivantes de l'objet descripteur :

  • inscriptible : C'est un booléen qui indique si la valeur de la propriété peut être modifiée. peut être modifiée ; sa valeur par défaut est false.
  • configurable : Il s'agit d'un booléen qui indique si le descripteur de la propriété du descripteur de la propriété peut être modifié ou si la propriété elle-même peut être supprimée. valeur par défaut est false
  • énumérable : Il s'agit d'un booléen indiquant si la propriété peut être accessible dans une boucle sur les propriétés de l'objet ; sa valeur par défaut est false
  • valeur : Ceci représente la valeur associée à la propriété. valeur par défaut est indéfinie

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X