JavaScript getter для всех свойств - PullRequest
44 голосов
/ 15 июня 2009

Короче говоря: я нахожусь в ситуации, когда мне нужен геттер в стиле PHP, но в JavaScript.

Мой JavaScript работает только в Firefox, поэтому для меня вполне подходит JS для Mozilla.

Единственный способ найти геттер JS - указать его имя, но я бы хотел определить геттер для всех возможных имен. Я не уверен, возможно ли это, но я бы очень хотел знать.

Ответы [ 7 ]

58 голосов
/ 20 марта 2016

Proxy может это сделать! Я так счастлив, что это существует! Ответ дается здесь: Существует ли javascript-эквивалент метода __getattr__ в python? Перефразируя своими словами:

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"

Прокси за победу! Ознакомьтесь с документами MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

Работает в chrome, firefox и node.js. Недостатки: не работает в IE - чертовски IE. Скоро.

48 голосов
/ 15 июня 2009

Самое близкое, что вы можете найти, это __ noSuchMethod __ , который является JavaScript-эквивалентом PHP __call ().

К сожалению, нет эквивалента __get / __ set, что является позором, потому что с их помощью мы могли бы реализовать __noSuchMethod__, но я пока не вижу способа реализации свойств (как в C #) с использованием __noSuchMethod __.

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

foo.bar(1, 2);
24 голосов
/ 10 апреля 2017

Если вы кодируете в ES6, вы можете комбинировать прокси и класс, чтобы получить красивый код вроде php :

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

это привязывается к обработчику, так что вы можете использовать его вместо цели.

Примечание: в отличие от PHP, прокси обрабатывает все запросы свойств.

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

Вы можете проверить, какие браузеры поддерживают прокси http://caniuse.com/#feat=proxy и класс http://caniuse.com/#feat=es6-class. Узел 8 поддерживает оба.

5 голосов
/ 17 октября 2012

Если вам действительно нужна работающая реализация, вы можете «обмануть» свой путь, проверяя второй параметр с undefined, это также означает, что вы можете использовать get для фактической установки параметра.

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 голосов
/ 15 июня 2009

Javascript 1.5 имеет геттер / сеттер синтаксический сахар . Это очень хорошо объяснил Джон Резиг здесь

Это не достаточно универсально для веб-использования, но, безусловно, они есть у Firefox (и Rhino, если вы когда-нибудь захотите использовать его на стороне сервера).

1 голос
/ 13 ноября 2014

В итоге я воспользовался ответом nickfs, чтобы построить собственное решение. Мое решение автоматически создаст функции get_ {propname} и set_ {propname} для всех свойств. Он проверяет, существует ли функция, прежде чем добавлять их. Это позволяет вам переопределить метод get или set по умолчанию нашей собственной реализацией без риска его перезаписи.

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 голос
/ 15 июня 2009

Если вы ищете что-то вроде функции PHP __get(), я не думаю, что Javascript предоставляет такую ​​конструкцию.

Лучшее, что я могу придумать, - это циклически перебирать нефункциональные члены объекта и затем создавать соответствующую функцию "getXYZ ()" для каждого.

В изящном псевдо-коде:

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"
        };
    }
}
...