Ответ 1
На данный момент существует только одна вещь, которая может делать то, что вы хотите, но, к сожалению, не получила широкого распространения:
В настоящее время доступны только две рабочие реализации: в последних бета-версиях Firefox 4 (это было со времен предварительных выпусков FF3.7) и в node-proxy для серверного JavaScript -Chrome и Safari в настоящее время работают над it-.
Это одно из ранних предложений для следующей версии ECMAScript, это API, который позволяет вам реализовывать виртуализированные объекты (прокси), где вы можете назначать различные ловушки - обратные вызовы - которые выполняются в разных ситуациях, вы получаете полный контроль над тем, что в настоящее время -in ECMAScript 3/5- могут выполнять только хост-объекты.
Чтобы построить прокси-объект, вы должны использовать метод Proxy.create
, так как вас интересуют ловушки set
и get
, я оставлю вам очень простой пример:
var p = Proxy.create({
get: function(proxy, name) { // intercepts property access
return 'Hello, '+ name;
},
set: function(proxy, name, value) { // intercepts property assignments
alert(name +'='+ value);
return true;
}
});
alert(p.world); // alerts 'Hello, world'
p.foo = 'bar'; // alerts foo=bar
Попробуйте здесь.
Proxy API настолько нов, что даже не документирован в Центре разработчиков Mozilla, но, как я уже сказал, рабочая версия была включена с предварительных выпусков Firefox 3.7.
Объект Proxy
доступен в глобальной области видимости, а метод create
может принимать два аргумента: объект handler
, который представляет собой просто объект, содержащий свойства, названные в качестве ловушек, которые вы хотите реализовать, и необязательный proto
], который позволяет вам указать объект, от которого наследуется ваш прокси.
Доступны следующие ловушки:
// TrapName(args) Triggered by
// Fundamental traps
getOwnPropertyDescriptor(name): // Object.getOwnPropertyDescriptor(proxy, name)
getPropertyDescriptor(name): // Object.getPropertyDescriptor(proxy, name) [currently inexistent in ES5]
defineProperty(name, propertyDescriptor): // Object.defineProperty(proxy,name,pd)
getOwnPropertyNames(): // Object.getOwnPropertyNames(proxy)
getPropertyNames(): // Object.getPropertyNames(proxy)
delete(name): // delete proxy.name
enumerate(): // for (name in proxy)
fix(): // Object.{freeze|seal|preventExtensions}(proxy)
// Derived traps
has(name): // name in proxy
hasOwn(name): // ({}).hasOwnProperty.call(proxy, name)
get(receiver, name): // receiver.name
set(receiver, name, val): // receiver.name = val
keys(): // Object.keys(proxy)
Единственный ресурс, который я видел, кроме самого предложения, это следующий учебник:
Изменить: Появляется дополнительная информация. Брендан Айх недавно выступил с докладом на конференции JSConf.eu, его слайды можно найти здесь:
ОБНОВЛЕНИЕ (2019-08-14):
Эмуляция __noSuchMethod__ с прокси ES6
Реализуя ловушки при доступе к свойству, вы можете эмулировать поведение нестандартной ловушки __noSuchMethod__
:
function enableNoSuchMethod(obj) {
return new Proxy(obj, {
get(target, p) {
if (p in target) {
return target[p];
} else if (typeof target.__noSuchMethod__ == "function") {
return function(...args) {
return target.__noSuchMethod__.call(target, p, args);
};
}
}
});
}
// Example usage:
function Dummy() {
this.ownProp1 = "value1";
return enableNoSuchMethod(this);
}
Dummy.prototype.test = function() {
console.log("Test called");
};
Dummy.prototype.__noSuchMethod__ = function(name, args) {
console.log('No such method ${name} called with ${args}');
return;
};
var instance = new Dummy();
console.log(instance.ownProp1);
instance.test();
instance.someName(1, 2);
instance.xyz(3, 4);
instance.doesNotExist("a", "b");