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 4th 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 with new functionality and adding additional function calls to existing events, that run in the correct order.

So, any idea how to put functions by reference into arrays/objects ?


Edit: 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();
share|improve this question
It is a reference to the function. You're changing what shout is pointing at, the array still references the same function. – Shmiddty 2 days ago
Thanks Shmiddty. – FTav 2 days ago

2 Answers

up vote 2 down vote accepted

I agree with T.J.'s answer. However, if you wanted to do some kind of workaround, you could create a function that always does a "just in time" lookup from a cache of functions. See this fiddle

var getFunctionRef = function(funcName)
{
    return function() { global[funcName](); };
}

var global = { };
var arr = [];

global.shout = function() { alert('hello'); }

arr[0] = getFunctionRef('shout');

global.shout = function() { alert('world'); }

arr[0]();

It's a very basic example. There are more extensive ways of doing it. But this should demonstrate the concept.

share|improve this answer
Thank you Eli, T. J. explained in a very good way, why this is not really that much of a reference than passing by value, but your solution also pushed me in the right direction to solve my problem! – FTav 2 days ago

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 <code>shout</code> 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 <code>shout</code> and <code>dasarray</code> 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 <code>shout</code> pointing to second function, <code>dasarray</code> 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!
share|improve this answer
Thanks for your answer, that made it clear, but @EliGassert also provided a very nice workaround :) – FTav 2 days ago
@FTav: Glad that helped. Due respect to Eli, but I think there's a better way to do it. That's more complex than necessary. FWIW, I've given a more direct way above. – T.J. Crowder 2 days ago
No qualms about your solution. It's clean (especially the new edits). +1 to your answer. My solution was very generic and doesn't serve a real-world scenario. I imagine another layer or two of abstraction, separating the dasarray from the caller. Otherwise, you could even get more direct and change global to dasarray and modify the functions directly in the array. But I imagine the real solution will be more complicated than the example given and solutions we've presented. – Eli Gassert 2 days ago
I updated my question with a pseudo real solution :) – FTav 2 days ago

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.