Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript array/object of functions by reference

Given:

function shout(){ alert('Hello!'); }
var dasarray = [ shout ];

shout();
dasarray[0]();

shout = function(){ alert('World!'); }

shout();
dasarray[0]();

Output:

Hello!

Hello!

World!

Hello!

I would've expected that dasarray received a reference to the function shout, but sadly the fourth output is also hello. If I assume right, I was able to modify the shout function correctly, but this leads to my assumption that the function was not passed by reference into dasarray.

Instead of an array I already tried this example with an object:

dasarray = { myfunction: shout }

With the same, disappointing, result.

My intention is to have an array/object of/with functions that are run in order and that can be extended in real time.

For example, extending the JavaScript code with new functionality and adding additional function calls to existing events that run in the correct order.

So, how can I put functions by reference into arrays/objects?


Thanks for the good answers. I just wanted to explain that I chose Eli's answer, because it lead me to this setup:

zzz = {
    calls: [],
    shout: function(message) {
        alert('Shouting: ' + message);
    },
    initialize: function () {
        zzz.calls.push(['shout','Hello World']);
        zzz.calls.push(['shout','this is']);
        zzz.calls.push(['shout','my last shout!']);
        zzz.run();

        zzz.shout = function(){ alert('modified!'); };
        zzz.run();
    },
    run: function () {
        $.each(zzz.calls, function(){ zzz[this[0]](this[1]); }); // <- Using jQuery $.each here, just to keep it easy
    }
};

zzz.initialize();
like image 286
FTav Avatar asked Aug 13 '26 02:08

FTav


1 Answers

I would've expected that dasarray received a reference to the function shout

It does. It does not receive a reference to the variable shout. (The symbol defined by the name of a function in a function declaration is, for virtually all intents and purposes, a variable — which is why you can assign to it later.) So your later line changing that variable:

shout = function(){ alert('World!'); }

...has no effect on the reference to the earlier function in dasarray.

Think of object references as a value saying where to find an object. When you do:

function shout(){ alert('Hello!'); }

...the symbol shout receives a value saying where that function is found, like this:

Variable shout pointing to function object

Then when you do:

var dasarray = [ shout ];

...that value is put in the first entry in the array. Now the symbol shout and the first entry in dasarray both have the same value, which tells the JavaScript engine where to find that function object in memory. So we have this:

Variable shout and dasarray entry 0 pointing to same function object

But the variable shout and the entry in dasarray have no connection whatsoever to each other.

Then you do this:

shout = function(){ alert('World!'); }

...that creates a new function and stores a new value in the variable shout saying where that new function is. But that has no effect on the value stored in dasarray's entry 0. We end up with this:

Var shout pointing to second function, dasarray entry 0 pointing to first function

I'm saying "value" a lot above because that's what an "object reference" is: A value, just like the value 5. It's just that the way that value is used is to look up where an object is. When you assign that value from one variable to another, the value gets copied, just like the value 5 gets copied when you copy it from one variable to another.

I can't say I like Eli's workaround much, I'd rather just be much more direct about it and use objects in the simple way:

var obj = {
    shout: function() { alert("Hello!"); }
};
var dasarray = [ obj ];

obj.shout();                               // Hello!
dasarray[0].shout();                       // Hello!

obj.shout = function() { alert("World"); };

obj.shout();                               // World!
dasarray[0].shout();                       // World!
like image 124
T.J. Crowder Avatar answered Aug 15 '26 18:08

T.J. Crowder



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!