JavaScript getter для всех свойств

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

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

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

7 ответов


вы можете найти __noSuchMethod__, что является эквивалентом JavaScript для PHP __call().

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

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

foo.bar(1, 2);

Proxy можете сделать это! Я так рада, что это существует!! Здесь дается ответ:существует ли javascript-эквивалент метода __getattr _ _ python? . Перефразируя мои собственные слова:--5-->

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 - freakin IE. Скоро.


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

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

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

Примечание: В отличие от 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 поддерживать как.


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

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


Если вам действительно нужна реализация, которая работает, вы можете "обмануть" свой путь, Протестировав второй параметр против 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;
        }
    }
};

Если вы ищете что-то вроде 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"
        };
    }
}

Я закончил тем, что использовал ответ 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;
                    };
                }
            })();
        }
    }