views:

251

answers:

3

I can call a function directly (I'll use alert as an example) like so

alert("Hello World!");  // pops up an alert window

However, when I put a function in an object, calling it no longer works:

d = {func: alert};
d.func("Hello World!");    // doesn't do anything
d["func"]("Hello World!"); // also doesn't do anything

I figured maybe I needed to explicitly pass in a blank this argument, so I tried

d.func(null, "Hello World!") // still nothing

but to no avail. Interestingly, this does work

d.func.apply(null, ["Hello World!"]);  // success!

but that's so gratuitously verbose it makes my teeth hurt (to quote JWZ). Is there a more concise, less ugly way?

+2  A: 

If you try this:

function test(x) {
    alert(x);
}
var x = {func: test}
x.func('Hi!');

It works as you expect. When I try doing this to alert directly Firebug gives me the following error message:

[Exception... "Cannot modify properties of a WrappedNative"
nsresult: "0x80570034 (NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN)"
location: "JS frame :: http://stackoverflow.com/questions/859466/javascript-function-in-an-object-hash :: anonymous :: line 72" data: no]

So I am guessing it's a security thing or something to do with it being a native function.

Paolo Bergantino
Interesting - I didn't get that message in Firebug, so I guess my version behaves differently. I guess this problem is just limited to the alert function and user-defined functions work just fine. However, I can't figure out any reason for this behavior - we're not modifying alert in any way, so I can't tell why this would be harmful.
Eli Courtwright
+1  A: 

I've always done it like this:

var d = Object;

d.hello = function(msg) {
                    alert(msg)
                    };

d.hello('hello');


Of course, you can also use PrototypeJS to get all object oriented:

var Message = Class.create( {
              display:  function(msg) {
                  alert(msg);
               }
           });

var msg = new Message();

msg.display('hello');
Mark Biek
+3  A: 

Functions in JavaScript are passed by value. The alert() function is natively implemented, meaning it has no JavaScript value. Depending on your browser, the meaninfulness (forgive me for that) of that native wrapper varies. Your code actually works in Google Chrome, but won't work in Firefox, and off the top of my head I'm going to say it won't work in Internet Explorer, either, which is generally not friendly about modifying native objects and functions. You could use the following instead:

d = {
    func: function (message) {
        alert(message);
    }
};
Andrew Noyes
Ahh, you seem to be correct. Inspecting alert tells me that it doesn't have all of the properties that regular Javascript objects have, since it's "built-in" as you say. Thanks for testing in Chrome and for somewhat explaining the behavior.
Eli Courtwright
I actually have an amendment to make--it doesn't work in Chrome... all the time. The code, exactly as you have it written, causes and illegal invocation error. However, if you simply make a reference to alert in the global namespace, i.e.: var myAlert = alert; myAlert("Hello, World!"); // Works!This looks like finicky browser behavior to me.
Andrew Noyes