2013 и 2015 Обновление (исходный ответ от 2011 г. см. Ниже) :
Это изменилось в соответствии со спецификацией ES2015 (также называемой "ES6"):JavaScript теперь имеет прокси .Прокси позволяют вам создавать объекты, которые являются настоящими прокси для (фасадов) других объектов.Вот простой пример, который превращает любые значения свойств, которые являются строками, во все заглавные буквы при извлечении:
"use strict";
if (typeof Proxy == "undefined") {
throw new Error("This browser doesn't support Proxy");
}
let original = {
"foo": "bar"
};
let proxy = new Proxy(original, {
get(target, name, receiver) {
let rv = Reflect.get(target, name, receiver);
if (typeof rv === "string") {
rv = rv.toUpperCase();
}
return rv;
}
});
console.log(`original.foo = ${original.foo}`); // "original.foo = bar"
console.log(`proxy.foo = ${proxy.foo}`); // "proxy.foo = BAR"
Операции, которые вы не переопределяете, имеют поведение по умолчанию.Выше мы переопределяем get
, но есть целый список операций, в которые вы можете подключиться.
В списке аргументов функции-обработчика get
:
target
- это проксируемый объект (в нашем случае original
). name
- это (конечно) имя извлекаемого свойства, которое обычно является строкой, но также может быть символом. receiver
- это объект, который следует использовать как this
в функции получения, если свойство является средством доступа, а не свойством данных.В обычном случае это прокси или что-то, что наследуется от него, но оно может быть чем угодно, так как ловушка может быть вызвана Reflect.get
.
Это позволяет вам создатьобъект с нужной вам функцией getter и setter:
"use strict";
if (typeof Proxy == "undefined") {
throw new Error("This browser doesn't support Proxy");
}
let obj = new Proxy({}, {
get(target, name, receiver) {
if (!Reflect.has(target, name)) {
console.log("Getting non-existent property '" + name + "'");
return undefined;
}
return Reflect.get(target, name, receiver);
},
set(target, name, value, receiver) {
if (!Reflect.has(target, name)) {
console.log(`Setting non-existent property '${name}', initial value: ${value}`);
}
return Reflect.set(target, name, value, receiver);
}
});
console.log(`[before] obj.foo = ${obj.foo}`);
obj.foo = "bar";
console.log(`[after] obj.foo = ${obj.foo}`);
Вывод вышеприведенного:
Getting non-existent property 'foo'
[before] obj.foo = undefined
Setting non-existent property 'foo', initial value: bar
[after] obj.foo = bar
Обратите внимание, как мы получаем «несуществующее» сообщение, когда пытаемся получить foo
когда он еще не существует, и снова, когда мы его создаем, но не после этого.
Ответ от 2011 (см. выше для обновлений 2013 и 2015 годов):
Нет, в JavaScript нет функции всеобъемлющего свойства.Используемый вами синтаксис аксессора описан в Разделе 11.1.5 спецификации и не предлагает никаких подстановочных знаков или чего-то подобного.
Конечно, вы можете реализоватьфункция, чтобы сделать это, но я предполагаю, что вы, вероятно, не хотите использовать f = obj.prop("foo");
вместо f = obj.foo;
и obj.prop("foo", value);
вместо obj.foo = value;
(что было бы необходимо для функции, чтобы обрабатывать неизвестные свойства).
FWIW, функция получения (я не беспокоился о логике установки) выглядела бы примерно так:
MyObject.prototype.prop = function(propName) {
if (propName in this) {
// This object or its prototype already has this property,
// return the existing value.
return this[propName];
}
// ...Catch-all, deal with undefined property here...
};
Но, опять же, я не могу представить, что вы действительно хотите сделатьчто из-за того, как это меняет то, как вы используете объект.