JavaScript getter для всех свойств
Короче говоря: я в ситуации, когда мне нужен геттер в стиле PHP, но в JavaScript.
Мой JavaScript работает только в Firefox, поэтому Mozilla специфический JS в порядке.
Единственный способ, которым я могу найти, чтобы получить JS getter, требует указания его имени, но я бы хотел определить getter для всех возможных имен. Я не уверен, что это возможно, но я очень хотел бы знать.
Ответы
Ответ 1
Ближе всего вы можете найти __ noSuchMethod__, который является эквивалентом JavaScript PHP __call().
К сожалению, нет эквивалента __get/__ set, что является позором, потому что с ними мы могли бы реализовать __noSuchMethod__, но я пока не вижу способа реализовать свойства (как на С#) с помощью __noSuchMethod __.
var foo = {
__noSuchMethod__ : function(id, args) {
alert(id);
alert(args);
}
};
foo.bar(1, 2);
Ответ 2
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 - freakin IE. Скоро.
Ответ 3
Если вы кодируете в 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. Node 8 поддерживают оба.
Ответ 4
Javascript 1.5 имеет getter/setter синтаксический сахар. Он очень хорошо объяснил Джон Ресиг здесь
Это не достаточно общее для использования в Интернете, но, безусловно, Firefox имеет их (также Rhino, если вы когда-либо захотите использовать его на стороне сервера).
Ответ 5
Если вам действительно нужна реализация, которая работает, вы можете "обманывать" свой путь arround, проверяя второй параметр на 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;
}
}
};
Ответ 6
Если вы ищете что-то вроде 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"
};
}
}
Ответ 7
В итоге я использовал ответ 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;
};
}
})();
}
}