1

I am trying to do something similar to what Google Analytics is doing. I want to push a function name along with parameters into an array and then execute the function name along with the parameter.

For example:

    var _test = _test || [];
    _test.push(['setName', 'Todd']);

And execute setName in here:

var widget = function () {

    function _private_setName(a) {
        console.log(a);
    }

    return{
       setName:_private_setName
    };  
}();

console.log(_test);

_test contains the function name and parameter, but how can i execute the function?

2 Answers 2

6

You have to iterate over the array. The first element of each inner array will be the method name, which you can use with bracket notation to access the method of the object. To pass the remaining elements as arguments to the method, use .apply.

Example:

if (window._test) {
    for (var i = 0; i < _test.length; i++) {
        var method = _test[i].shift(); // this modifies the inner array!
        widget[method].apply(widget, _test[i]);
    }
}

Of course you should add some checks so that you try to call methods that don't exist.

To make this "pattern" really work you also have to handle calls to _test.push properly after the script was loaded. As it is now, any elements that are added to the array after the script was loaded would simply be ignored.
One solution would be to replace _test after you processed the existing _test array with an object having a .push method. Since widget exists now, we can immediately execute the function call. For the calling code, the interface does not change.

// iterate over _test and process data 

window._test = { // overwrite _test
    push: function(cmd) {
        var method = cmd.shift();
        widget[method].apply(widget, cmd);
    }
};

As you can see, this would only work if _test is global. I think in Google Analytics, _gaq has to be global as well.


The good aspect about this approach is that you don't have wait until widget is ready. A drawback could be that the code is not as clear is just waiting for the script to load and then make "normal" method calls.

So, when would you use one or the other? Personally I would choose to simple wait until the script is loaded, e.g.

loadScript('scripturl', function() {
   // script is ready, do stuff
});

However, there are cases where you cannot wait until a script was loaded. For example if you want to track user interaction (what Google Analytics does). If you also want to include the script dynamically, i.e. there is no script tag for it in the HTML, you have to use some form of command queue.

Sign up to request clarification or add additional context in comments.

11 Comments

Very nice! How could i also capture onclick pushes? Like this: <a href="#" onclick="_test.push(['setName', 'Brian']);">Test click</a>
I would create a function which accepts the array as argument, e.g. addCommand(['setName', 'Brian']). Then inside the function you would ensure that _test is defined.
Not sure that i follow :) Could you show an example how to capture onclick?
Define a function like function addCommand(cmd) { window._test = window._test || []; window._test.push(cmd); } in the head and call it like any other function: <a href="#" onclick="addCommand(['setName', 'Brian']);">Test click</a>.
Couldent get the last example to work, but it seems to do exactly what i want.. i get TypeError: Array.prototyp is undefined
|
0
var _test = _test || [];
_test.push(['setName', 'Todd']);
_test.push(['setName', 'Joe']);

for(var i = 0; i < _test.length; i++){
    widget[_test[i][0]](_test[i][1]);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.