Is it possible to capture when a (any) property of an object is accessed, or attempting to be accessed?
Example:
I have created custom object Foo
var Foo = (function(){
var self = {};
//... set a few properties
return self;
})();
Then there is some action against Foo
- someone tries to access property bar
Foo.bar
Is there way (prototype, perhaps) to capture this? bar
may be undefined on Foo
. I could suffice with capturing any attempted access to undefined properties.
For instance, if bar
is undefined on Foo
, and Foo.bar
is attempted, something like:
Foo.prototype.undefined = function(){
var name = this.name; //name of property they attempted to access (bar)
Foo[name] = function(){
//...do something
};
return Foo[name];
}
But functional, unlike my example.
Concept
Foo.* = function(){
}
Background
If I have a custom function, I can listen for every time this function is called (see below). Just wondering if it's possible with property access.
Foo = function(){};
Foo.prototype.call = function(thisArg){
console.log(this, thisArg);
return this;
}
Yes, this is possible in ES2015+, using the Proxy. It's not possible in ES5 and earlier, not even with polyfills.
It took me a while, but I finally found my previous answer to this question. See that answer for all the details on proxies and such.
Here's the proxy example from that answer:
const obj = new Proxy({}, {
get: function(target, name, receiver) {
if (!(name in target)) {
console.log("Getting non-existant property '" + name + "'");
return undefined;
}
return Reflect.get(target, name, receiver);
},
set: function(target, name, value, receiver) {
if (!(name in target)) {
console.log("Setting non-existant 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);
obj.foo = "baz";
console.log("[after] obj.foo = " + obj.foo);
Live Copy:
"use strict";
const obj = new Proxy({}, {
get: function(target, name, receiver) {
if (!(name in target)) {
console.log("Getting non-existant property '" + name + "'");
return undefined;
}
return Reflect.get(target, name, receiver);
},
set: function(target, name, value, receiver) {
if (!(name in target)) {
console.log("Setting non-existant 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);
obj.foo = "baz";
console.log("[after] obj.foo = " + obj.foo);
When run, that outputs:
Getting non-existant property 'foo' [before] obj.foo = undefined Setting non-existant property 'foo', initial value: bar [after] obj.foo = bar [after] obj.foo = baz