3

Is it possible to listen to any function invocation or state change

I have a object that wrap another

function wrapper(origiObj){
   this.origObj = origObj;
}
var obj = wrapper(document);//this is an example
var obj = wrapper(db);//this is an example

now everytime someone tries to invoke obj.innerHTML or obj.query(..)

I would like to listen to that..

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
ciochPep
  • 2,472
  • 4
  • 26
  • 30

3 Answers3

2

Yes, it's possible: functions are easy, and properties has to be watched

function FlyingObject(obj){
    this.obj = obj;
    for(var p in obj){
        if(typeof obj[p] == 'function'){
            console.log(p);
            this[p] = function(){
                console.log("orig func");
            };
        }else{
            this.watch(p,function(){
                console.log("orig property");
            });
        }
    }
}
var obj = {
    f:function(a,b){ return a+b},
    m:1
};
var fo = new FlyingObject(obj);


fo.m = 5;

fo.f(1,4);

If your browser/node.js doesn't support Object.watch, check this out: Object.watch() for all browsers?

Community
  • 1
  • 1
DuduAlul
  • 6,313
  • 7
  • 39
  • 63
0

Yes you can, define a getter/setter for properties and a shadow function for the function like this: http://jsfiddle.net/fHRyU/1/.

function wrapper(origObj){
   var type = origObj.innerHTML ? 'doc' : 'db';
   if(type === "doc") {

      var orig = origObj.innerHTML;

      origObj.__defineGetter__('innerHTML',
                               function() {
       // someone got innerHTML
          alert('getting innerHTML');
          return orig;
      });

      origObj.__defineSetter__('innerHTML',
                               function(a) {
       // someone set innerHTML
          alert('setting innerHTML');
          orig = a;
      });

   } else if(type === "db") {

       var orig = origObj.query;

       origObj.query = function() {
           //someone called query;
           alert('calling query');
           orig.apply(this, arguments);
       };

   }

   return origObj;
}

var obj = wrapper(document.body);
obj.innerHTML = 'p';
alert(obj.innerHTML);

var db = function() {}
db.query = function() {alert('foo');}

obj = wrapper(db);
obj.query();
pimvdb
  • 151,816
  • 78
  • 307
  • 352
  • A couple things to point out about this: no IE support, and you have to manually wrap every property you may want to catch. –  Jun 22 '11 at 16:26
  • 3
    But node.js is not IE if I'm not wrong. But you're correct about your second point. – pimvdb Jun 22 '11 at 16:27
  • :) Didn't notice the `node.js` tag –  Jun 22 '11 at 16:28
  • The wrapper could easily be rewritten to work for any obligatory property and trigger events. – zzzzBov Jun 22 '11 at 16:32
0

edit: "Deleting" answer since it's tagged node.js, leaving it in case it happens to be useful to anyone else:

The general answer is no, it isn't. At least not in every browser, so any solution anyone gives isn't going to work in many cases.

There are a few things that can work, but again there is horrible support for them:

  • dom modified events (FF only, I believe)
    • DOMAttrModified
    • DOMNodeInserted
    • DOMNodeRemoved
    • etc
  • object.watch (FF only)