web-dev-qa-db-fra.com

Comment définir setter / getter sur prototype

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

Après ma question précédente sur la façon de faire de la sous-classe 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, comment définir un setter/getter sur le prototype avec cette syntaxe?

Autrefois, je faisais:

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

    get myProperty() {
        // code.
    }
}

Mais évidemment, 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, tant qu'il est pris en charge par GJS (je suppose que cela signifie Spidermonkey?), Cela ne me dérange pas s'il n'est pas compatible.

72

Utilisation d'une déclaration littérale d'objet (manière la plus simple):

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

En utilisant Object.defineProperty (sur les navigateurs modernes prenant en charge ES5):

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

Ou en utilisant __defineGetter__ et __defineSetter__ ( [~ # ~] déconseillé [~ # ~] ):

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

Utilisez Object.defineProperty() sur Subclass.prototype. Il y a aussi __defineGetter__ et __defineSetter__ disponible sur certains navigateurs, mais ils sont obsolètes. Pour votre exemple, ce serait:

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

Je pense que vous vouliez faire de cette façon:

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
33

Pour définir des setters et des 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 le raccourcir avec une fonction utilitaire:

//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 "ceci" lorsque nous l'appelons.

Avec ce code, vous vous retrouvez avec une propriété get/set à l'intérieur du prototype de l'objet, pas l'instance, comme la question posée.

(Testé Firefox 42, Chrome 45)

5
Mackraken

Spécifiez un getter ou un setter dans les constructeurs par la méthode Object.defineProperty (). Cette méthode prend trois arguments: le premier argument est l'objet auquel ajouter la propriété, le second est le nom de la propriété et 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 d'Object.defineProperty () donne plus de contrôle sur notre définition de propriété. Par exemple, nous pouvons spécifier si la propriété que nous décrivons peut être supprimée ou redéfinie dynamiquement, si sa valeur peut être modifiée, etc.

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

  • accessible en écriture: il s'agit d'un booléen qui indique si la valeur de la propriété 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é peut être modifié ou la propriété elle-même peut être supprimée; sa valeur par défaut est false
  • énumérable: il s'agit d'un booléen indiquant si la propriété est accessible en boucle sur les propriétés de l'objet; sa valeur par défaut est false
  • valeur: cela représente la valeur associée à la propriété; sa valeur par défaut n'est pas définie
4
Michael Horojanski