2

Is it possible to get notification from within JavaScript when calling an object's methods?

Example:

o.foo(arg1);

function o_ongenericcall(name, arguements)
{
 switch (name)
 {
  case "foo":
   // Do something 
   break;
 }
}

In the above example, o is the object and I would like o_ongenericcall to be raised when any method is trying to be invoked.

gen_Eric
  • 223,194
  • 41
  • 299
  • 337
vbguyny
  • 1,170
  • 1
  • 10
  • 29

5 Answers5

1

You could create a kind of proxy on the object's function calls.

// create a copy of the original function
o.foo_ = o.foo;

// replace the original function with a wrapper that calls the notification
o.foo = function() { 
    console.log("notify: foo(" + arguments[0] ")"); 
    o_ongenericcall("foo", arguments);
    this.foo_.apply(this, arguments); 
}

o.foo("testing");

notify: foo(testing)

Note that you could set this up by looping through the object's properties:

for (var member in o) {
   if (typeof o[member]=="function") {
      console.log(member);
      applyNotificationProxy(o, member);
   }
}

DEMO

McGarnagle
  • 101,349
  • 31
  • 229
  • 260
  • Thanks for the example, but this only works for an object that has actual members attached to it. It is sort of a "fake" object that I am using. It would be similar to how the dynamic keyword works in C#. It appears that what I am looking for isn't possible... yet. – vbguyny Sep 22 '12 at 03:33
0

I don't think it can be done natively.

You probably want to implement the Observer Pattern.

Richard JP Le Guen
  • 28,364
  • 7
  • 89
  • 119
0

No, this is only possible if you called o_ongenericcall from the foo method.

However, you can easily decorate all methods on an object with that invocation:

function decorated(obj) {
    var res = {}; // you might also use obj itself if you don't want to create a new one
    for (var p in obj) 
        if (typeof obj[p] == "function")
            (function(orig, p) {
                res[p] = function() {
                     o_ongenericcall(p);
                     return orig.apply(this, arguments);
                };
            })(obj[p], p);
        else
            res[p] = obj[p];
}

obj = decorated({foo:function(){console.log("foo");}});
obj.foo(); // calls o_ongenericcall, then logs "foo"
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

This will probably not help you much, but what you need is a Proxy. This is a fairly new and unstable API in Javascript, not yet part of any standard, and is not really supported by any browser. V8 supports proxies, but does not expose that functionality to Chrome; you can however enable them in Node.js by executing it with a --harmony-proxies parameter.

Community
  • 1
  • 1
lanzz
  • 42,060
  • 10
  • 89
  • 98
  • I though of that, but wouldn't a proxy only be able to log the accessing of the property, not the execution of the function? At least, there is the decoration step (see my or dbaseman's answers) missing. – Bergi Sep 20 '12 at 19:22
  • @Bergi You can implement a `get` trap that wraps callable properties into an additional function that calls the required handler. The advantage over explicit decoration is that, well, you don't have to do it explicitly. The disadvantage is the dependency on proxies :) – lanzz Sep 20 '12 at 19:28
0

Check AOP (Aspect Oriented Programming: Wikipedia) then, check this: AOP from Stackoverflow

Community
  • 1
  • 1
jodarove
  • 130
  • 3