web-dev-qa-db-fra.com

JavaScript getter pour toutes les propriétés

Longue histoire: je suis dans une situation où j'aimerais un getter de style PHP, mais en JavaScript.

Mon JavaScript n’exécute que dans Firefox. JS, spécifique à Mozilla, me convient donc.

La seule façon pour moi de créer un getter JS nécessite de spécifier son nom, mais j'aimerais définir un getter pour les noms all noms possibles. Je ne sais pas si cela est possible, mais j'aimerais beaucoup savoir.

41
arantius

Le plus proche que vous pouvez trouver est _NOSUCHMETHOD_ , qui est l'équivalent JavaScript de __call () de PHP.

Malheureusement, il n'y a pas d'équivalent de __get/__ set, ce qui est dommage, car nous aurions pu implémenter __noSuchMethod__, mais je ne vois pas encore de moyen d'implémenter des propriétés (comme en C #) à l'aide de __noSuchMethod__.

var foo = {
    __noSuchMethod__ : function(id, args) {
        alert(id);
        alert(args);
    }
};

foo.bar(1, 2);
47
Ionuț G. Stan

Proxy peut le faire! Je suis tellement contente que ça existe !! Une réponse est donnée ici: Existe-t-il un équivalent javascript de la méthode __getattr__ de python? . Pour reformuler dans mes propres mots:

var x = new Proxy({},{get(target,name) {
  return "Its hilarious you think I have "+name
}})

console.log(x.hair) // logs: "Its hilarious you think I have hair"

Proxy pour la victoire! Consultez les documents MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

Fonctionne en chrome, firefox et node.js. Inconvénients: ne fonctionne pas dans IE - freakin IE. Bientôt.

54
B T

Si vous codez dans ES6, vous pouvez combiner un proxy et une classe pour obtenir un joli code ressemblant à php:

class Magic {
    constructor () {
        return new Proxy(this, this);
    }
    get (target, prop) {
        return this[prop] || 'MAGIC';
    }
}

ceci se lie au gestionnaire, vous pouvez donc l'utiliser à la place de la cible.

Remarque: contrairement à PHP, le proxy gère toutes les demandes de propriétés.

let magic = new Magic();
magic.foo = 'NOT MAGIC';
console.log(magic.foo); // NOT MAGIC
console.log(magic.bar); // MAGIC

Vous pouvez vérifier quels navigateurs prennent en charge le proxy http://caniuse.com/#feat=proxy et la classe http://caniuse.com/#feat=es6-class . Le nœud 8 prend en charge les deux.

21
Ali

Javascript 1.5 a getter/settersucre syntactique . C'est très bien expliqué par John Resig ici

Ce n’est pas assez générique pour une utilisation Web, mais Firefox les a certainement (ainsi que Rhino, si vous voulez l’utiliser côté serveur).

5
Javier

Si vous avez vraiment besoin d'une implémentation qui fonctionne, vous pouvez "tromper" votre chemin en testant le second paramètre par rapport à undefined, cela signifie également que vous pouvez utiliser get pour définir réellement le paramètre.

var foo = {
    args: {},

    __noSuchMethod__ : function(id, args) {
        if(args === undefined) {
            return this.args[id] === undefined ? this[id] : this.args[id]
        }

        if(this[id] === undefined) {
            this.args[id] = args;
        } else {
            this[id] = args;
        }
    }
};
5
Vengarioth

J'ai fini par utiliser une réponse à un pseudo pour construire ma propre solution. Ma solution créera automatiquement les fonctions get_ {propname} et set_ {propname} pour toutes les propriétés. Il vérifie si la fonction existe déjà avant de les ajouter. Cela vous permet de remplacer la méthode get ou set par défaut avec notre propre implémentation sans risquer de l’écraser. 

for (o in this) {
        if (this.hasOwnProperty(o)) {
            var creategetter = (typeof this['get_' + o] !== 'function');
            var createsetter = (typeof this['set_' + o] !== 'function');
            (function () {
                var propname = o;
                if (creategetter) {
                    self['get_' + propname] = function () {
                        return self[propname];
                    };
                }
                if (createsetter) {
                    self['set_' + propname] = function (val) {
                        self[propname] = val;
                    };
                }
            })();
        }
    }
1
Kevin

Si vous cherchez quelque chose comme la fonction __get() de PHP, je ne pense pas que Javascript fournisse une telle construction.

Le mieux que je puisse faire est de parcourir en boucle les membres non-fonctions de l'objet, puis de créer une fonction "getXYZ ()" correspondante pour chacun.

En code pseudo-ish douteux:

for (o in this) {
    if (this.hasOwnProperty(o)) {
        this['get_' + o] = function() {
            // return this.o -- but you'll need to create a closure to
            // keep the correct reference to "o"
        };
    }
}
1
nickf

Je cherchais un moyen de recourir à des méthodes de proxy, pas seulement pour obtenir ou définir des propriétés, alors je suis venu avec cette solution combinant deux proxy: 

var original = {
    foo : function(arg1, arg2){
        return arg1 + " " + arg2;
    }
};

var proxy= new Proxy(function() {}, {
    get(target,name) {
        return new Proxy(function() {}, {
            apply: function(target, thisArg, argumentsList) {
                return original[name](argumentsList[0], argumentsList[1]);
            }});
    }
});


log(original.foo('one', 'two'));
log(proxy.foo('one', 'two'));    // this will execute original.foo('one', 'two')

https://jsfiddle.net/d4g0fx9e/

Le seul problème est cette ligne: 

return original[name](argumentsList[0], argumentsList[1]);

Est-ce que quelqu'un sait comment le rendre plus générique? sans avoir besoin de coder en dur le nombre de paramètres à passer (sans changer "d'original")

0
Enrique