0

I am trying to debug a large amount of JS Code inside a JS Object. There are somewhere around 150 functions inside this JS Object that are called individually through a separate script.

JS Object Example

var OmnitureCall = {
    reportA: function() {
        /* random actions */
    },
    reportB: function() {
        /* random actions */
    }
    ...
};

Other JS File Calling Object

OmnitureCall.reportA(...);

Somewhere in an external JS file, multiple reportA's are happening when only one is supposed to happen, which is why I would like to debug the main object and see when various report functions are being called and see where the double event is fired. However, the only way I can see doing this so far would to have a main function inside the OmnitureCall object that acts as a "handler" for all calls, and does some basic debugging and then runs the function that was called.

Example of JS Object Handler

var OmnitureCall = {
    handler: function(callback) {
        console.log('something is called');
        if(typeof(callback) === "function") {
            callback();
        }
    },
    reportA: function() {
        this.handler(function(){
            /* random actions */
        });
    },
    reportB: function() {
        this.handler(function(){
            /* random actions */
        });
    }
    ...
};

The downsides:

  1. There are 100+ functions I would have to copy and paste this.handler too and fix up
  2. In a majority of those functions the 'this' keyword is used to reference other functions within that OmnitureCall object, and I am worried the context of that referenced 'this' will be lost if it is all wrapped as a callback function and then called.

So my question to any JS devs, is there a way I can attach a function to this object that will always be called prior to whatever function was actually called (keep in mind I am also trying to document that name of said function that is being called so I can figure out what is being fired twice).

If that is not possible and the handler function idea is the only thing that may work, does anyone know how to retain the context of 'this' referring to the object as a whole if the function is passed as a parameter to handler and then called?

Much thanks..

2 Answers2

1

Proxies are what you're looking for, but they are not widely implemented - thus I wouldn't recommend it just yet. But for future's sake, this is what it'd look like:

// Your original object
var OmnitureCall = {
    reportA: function() {
        console.log(arguments, 'hello from report A');
    },
    reportB: function() {
        console.log(arguments, 'hello from report B');
    }
    // ...
};

// Create our proxy
var OmnitureCall = new Proxy(OmnitureCall, 
{
    // Since we want to see the calls to methods, we'll use get
    get: function(proxy, property)
    {
        // Tell us what we're calling
        console.log('calling ' + property);

        // Return it if it exists
        return proxy[property] || proxy.getItem(property) || undefined;
    }
});

// Returns "calling reportA", ["test", "foo"], "hello from report A":
OmnitureCall.reportA('test', 'foo');           

// Returns "calling reportB", [["array", "of", "args"]], "hello from report B":         
OmnitureCall.reportB(['args', 'is', 'an', 'array']); 

While Brett's code should work, you'd need to change all of the calls to the object. E.g. you can't do OmnitureCall.reportA(); anymore. It'd need to be OmnitureCall.handler('reportA'). You may or may not have control over this, or it may prove too difficult to change all of the references.

Using your original handler setup you can indeed pass the this reference using apply or call:

var OmnitureCall = {
    handler: function(callback, args) {
        if(typeof(callback) === "function") {
            callback.apply(this, args);
        }
    },
    reportA: function() {
        this.handler(function(){
            console.log(this);
        });
    },
    reportB: function() {
        this.handler(function(){
            console.log(arguments);
        }, arguments);
    }
    // ...
};

// Outputs Object {handler: function, reportA: function, reportB: function}
OmnitureCall.reportA();

// Outputs "test", ["foo", 1]
OmnitureCall.reportB('test', ['foo', 1]);
MisterPhilip
  • 2,452
  • 16
  • 16
0

You can do something like this http://jsfiddle.net/L4Z8U/ and just call the functions with the handler.

window.OmnitureCall = {
     handler: function(callback) {
        console.log('something is called',typeof(this[callback]));
        if(typeof(this[callback]) === "function") {
            this[callback]();
        }
    },
    reportA: function() {
         console.log('reportA fired');
     },
    reportB: function() {
        console.log('reportB fired');
    }

};

Edit: Ive doen this before using "this" in this context with no issues

BrettAHale
  • 791
  • 1
  • 5
  • 13