Ervadac
Ervadac

Reputation: 956

Setter for a dynamic property in javascript

I'm wondering if it's possible to have a setter for a dynamic property in Javascript ?

So this:

var myobj = new MyObj();

myobj.a_custom_prop = 'something';

Would call a function being able to retrieve 'a_custom_prop' and 'something'

To be clear, I would like a function similar to:

MyObj.property.define = function (prop, value) { };

to be called like this:

myobj.prop = value;

instead of:

myobj.define('prop', value);

Knowing that the name of the property is not static relative to myobj, otherwise I would have used:

Object.defineProperty(MyObj.prototype, 'a_custom_prop', {
   set: function (value) { /*...*/ }
});

Upvotes: 8

Views: 353

Answers (4)

Kyll
Kyll

Reputation: 7139

As Yoshi stated in a comment, it could be possible using Object.observe() from the ES7 draft.

However it's not exactly a "catch-all setter" because it will only be triggered after the property changed, not before. So, if for example you want to store the property somewhere else, you will have to delete it. Since the observe callback is asynchronous, it will be ran after the current callstack, meaning the new value can be immediately used before being altered.

Also, Chrome only for now.

The following snippet does some manipulations on the object through native setting and using Object.observe. It logs in the following order:

  1. I added this value: foobar
  2. The callback retrieves: foobar
  3. Value of foo.bar after deletion: undefined

Here goes:

var foo = {};

Object.observe(foo, function(changes) {
  var lastChanges = changes[changes.length - 1],
      newValue = lastChanges.object[lastChanges.name];

  console.log('The callback retrieves: ' + newValue);
  delete lastChanges.object[lastChanges.name];
}, ['add']);

foo.bar = 'foobar'; //Log n°2
console.log('I added this value: ' + foo.bar); //Log n°1
setTimeout(function() {
  console.log('Value of foo.bar after deletion: ' + foo.bar); //Log n°3
}, 0); //Execute after the observe callback

Due to the fact that it's in the ES7 draft, the previous might be completely wrong depending on when you read this.

Upvotes: 2

Konstantin Milyutin
Konstantin Milyutin

Reputation: 12366

What you want is similar to method missing in Ruby, where you define a function that will handle calls to undefined methods.

As you can read here: Does Javascript have something like Ruby's method_missing feature? JavaScript doesn't have something similar yet, but there is a proposal for ES6: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

Upvotes: 4

Liglo App
Liglo App

Reputation: 3819

No, it is currently not possible.

Upvotes: -1

ElDoRado1239
ElDoRado1239

Reputation: 4048

Couldn't you use something like this ?

function MyObj(){
 ...
 this.dynamicPropertyName = 'something';
 ...
}
MyObj.prototype.setThatProp = function(i){
 this[this.dynamicPropertyName] = i;
}
...
var myObj = new MyObj();
myObj.setThatProp(5);

EDIT:

Or something like this :

MyObj.prototype.__defineSetter__('prop', function(val){ this[this.dynamicPropertyName] = val; });
...
var myObj = new MyObj();
myObj.prop = 5;

Example use :

console test

Upvotes: 0

Related Questions