Reputation: 831
How can I specify a default getter for a prototype?
With default getter I mean a function that is called if obj.undefinedProperty123
is called.
I tried Object.prototype.get = function(property) {..} but this is not called in this case.
Upvotes: 18
Views: 13986
Reputation: 3087
I ran into this question because I wanted this behavior: if object property is undefined, return some default value instead.
const options = {
foo: 'foo',
bar: 'bar',
baz: 'baz'
};
function useOptionValue(optionName) {
// I want `options` to return a default value if `optionName` does not exist
const value = options[optionName];
// etc...
}
The simple way to do this (without Proxy or Object.defineProperty overkill for this use case) is like so:
function useOptionValue(optionName) {
const value = options[optionName] || defaultValue;
}
Or, if you want to get fancy, you could use a Symbol
:
const default = Symbol.for('default');
const options = {
foo: 'foo',
bar: 'bar',
baz: 'baz',
[default]: 'foobarbaz'
};
function useOptionValue(optionName) {
const value = options[optionName] || options[default];
}
Upvotes: 0
Reputation: 862
maybe late to ther party, let just add simple ES5 friendly "class creation": both string props and getters - i needed it for some ancient rewrite, to temporarily support IE (yes, that hurts, still found someone relying on ActiveX)
var MyObj = function () {
var obj = {
url: 'aabbcc',
a: function(){ return this.url;}
}
Object.defineProperty(obj, "urltoo", { get: function () { return this.url; } })
return obj;
}
var X = new MyObj();
x.url // aabbcc
x.urltoo // aabbcc
x.urltoo() // error - not a function
x.a() // aabbcc
x.a // ƒ (){ return this.url;}
Upvotes: 0
Reputation: 143
You want to create a Proxy:
const data = {};
const proxy = new Proxy(data, {
get: (target, prop) => {
console.log({ target, prop });
return "My Value";
},
set: (target, prop, value) => {
console.log({ target, prop, value });
return true;
},
});
proxy["foo"] = "bar";
const bar = proxy["foo"];
Upvotes: 4
Reputation: 115980
In ECMAScript 5, you can only intercept get/set operations on specific named properties (not universally all properties) via Object.defineProperty
:
Object.defineProperty(someObj, "someProp", {
get: function() {
console.log("you tried to get someObj.someProp");
return "foo";
}
});
Here, the get
function will run any time code tries to read someObj.someProp
.
In the upcoming ECMAScript 6 draft, this will be possible via proxies. A proxy has an underlying target object and set/get functions. Any time a set or get operation happens on any of a proxy's properties, the appropriate function runs, taking as arguments the proxy's target object, property name used, and the value used in a set
attempt.
var proxyHandler = {
get: function(obj, name){
console.log("you're getting property " + name);
return target[name];
},
set: function(obj, name, value) {
console.log("you're setting property " + name);
target[name] = value;
}
}
var underlyingObj = {};
// use prox instead of underlyingObj to use get/set interceptor functions
var prox = new Proxy(underlyingObj, proxyHandler);
Here, setting to getting property values on prox
will cause the set
/get
functions to run.
Upvotes: 14
Reputation:
You need to wait for the implementation of the ECMA6 "Proxy" system, designed to do exactly this. See http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies.
Upvotes: 4
Reputation: 19
Firefox it's possible with non-standard noSuchMethod:-
({__noSuchMethod__:function(){alert(1);}}).a();
Upvotes: 1
Reputation: 76766
What Gareth said, except it's __noSuchMethod__
.
Or maybe you were thinking of PHP?
Here's a very good article on the recently standardized property getters/setters, highlighting some previous non-standard incarnations.
summary: there's no standard 'catch-all' getter / setter (yet), but Object.defineProperty is the future.
Upvotes: 4
Reputation: 12904
I am not sure about what you are asking. But If you want a method to be called when the user attempts to Access object.nonExistingProperty
. I dont think there is any way to do that.
Upvotes: 0