0

I have written an answer where I had to write some decorators so I can hook into some function calls. However, I also want to hook into property setter calls as well but I'm not sure how that can be done.

In the answer, I wanted to hook into localStorage so that I can listen in on any changes. I did this by decorating the setItem() and removeItem() functions.

I know I could decorate functions by creating new ones that at some point calls the original.

var _setItem = localStorage.setItem;
localStorage.setItem = function () {
    _setItem.apply(this, arguments);
    localStorageObserver.notifySubscribers(arguments[0]);
};

This works well but there are other uses I wish to hook into, property accesses. The following is all equivalent for Storage objects:

localStorage.setItem('someProperty', 'value');
localStorage.someProperty = 'value';
localStorage['someProperty'] = 'value';

So I would need to hook into the last two cases but I'm not sure how that can be accomplished.

How does one write a decorator for dynamic properties? Is it at all possible?

I suppose I could manually create properties as they are set to hide what is done by the storage object but that doesn't seem very scalable. If there was a simple setProperty(name, value) function that I could hook into, I could decorate that. But as far as I know, that doesn't exist.

Community
  • 1
  • 1
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272

1 Answers1

0

How does one write a decorator for dynamic properties? Is it at all possible?

As of ES5, with true JavaScript objects, you can decorate properties you can find the names of, but not ones you don't yet know the names of, by replacing the property with a getter/setter pair via Object.defineProperty. In ES6, it will be possible to create "proxies" which allow you to completely put a facade in front of an existing object, intercepting get/set even on proeprties whose names you don't yet know, provided you're allow to replace the object with the facade.

In the ES5 case, the object in question would have to be a true JavaScript object, and there's no guarantee of that with host-provided objects like localStorage. In the ES6 case, you'd have to be able to overwrite localStorage with your own facade object, but as localStorage is host-provided there's no guarantee you can and good reason to believe you won't be allowed to (and having tried it on Chrome, you can't on Chrome).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I can live with that. At least with a facade object, I could just say that you must use the facade if you want to get the full benefit of the features that is being added. I think that would be reasonable in these kind of cases. – Jeff Mercado Oct 10 '14 at 20:35