Trying to call map( Menu.add , languages )
Here your problem is almost certainly that of JavaScript's lack of bound methods.
The setting of ‘this’ for a function is determined only at call-time, by examining how the method was obtained. If you say one of:
obj.method();
obj['method']();
JavaScript will pick up the reference to ‘obj’ and set ‘this= obj’ inside the method call. But if you say:
obj2.method= obj.method;
obj2.method();
Now ‘this’ inside the function will be obj2, not obj!
Similarly, if you pick the method off its object and refer to it as a first-class object:
var method= obj.method;
method();
There will be no object for ‘this’ to get set to, so JavaScript sets it to the global object (aka ‘window’ for web browsers). This is probably what is happening in your case: the ‘Menu.add’ method loses all reference to its owner ‘Menu’, so when it gets called back it is most likely unknowingly writing to members of the ‘window’ object instead of a menu.
This is of course highly unusual for an OO language, and almost never what you want, but hey, that's how JavaScript rolls. Causing silent, hard-to-debug errors is all part of the language's rationale.
To get around this problem you could pass an object reference in to your map function, then use Function.call()/apply() to set the ‘this’ reference correctly:
function mapMethod(fn, obj, sequence) {
for (var i= 0; i<sequence.length; i++)
sequence[i]= fn.call(obj, sequence[i]);
}
mapMethod(Menu.add, Menu, languages)
A more general way would be to bind function references manually, using a closure:
function bindMethod(fn, obj) {
return function() {
fn.apply(obj, arguments)
};
}
map(bindMethod(Menu.add, Menu), languages)
This capability will be built into a future version of JavaScript:
map(Menu.add.bind(Menu), languages)
And it is possible to add this facility to current browsers by writing to Function.prototype.bind?—?indeed, some JS frameworks do already. However note:
ECMAScript 3.1 promises you'll also be able to pass extra arguments into bind() to do partial function application, which requires a little more code than bindMethod() above;
IE loves to leak memory when you start leaving references like bound methods on DOM objects like event handlers.