views:

1342

answers:

5

JavaScript allows functions to be treated as objects--if you first define a variable as a function, you can subsequently add properties to that function. How do you do the reverse, and add a function to an "object"?

This works:

var foo = function() { return 1; };
foo.baz = "qqqq";

At this point, foo() calls the function, and foo.baz has the value "qqqq".

However, if you do the property assignment part first, how do you subsequently assign a function to the variable?

var bar = { baz: "qqqq" };

What can I do now to arrange for bar.baz to have the value "qqqq" and bar() to call the function?

A: 

JavaScript allows functions to be treated as objects--you can add a property to a function. How do you do the reverse, and add a function to an object?

You appear to be a bit confused. Functions, in JavaScript, are objects. And variables are variable. You wouldn't expect this to work:

var three = 3;
three = 4;
assert(three === 3);

...so why would you expect that assigning a function to your variable would somehow preserve its previous value? Perhaps some annotations will clarify things for you:

// assigns an anonymous function to the variable "foo"
var foo = function() { return 1; }; 
// assigns a string to the property "baz" on the object 
// referenced by "foo" (which, in this case, happens to be a function)
foo.baz = "qqqq";
Shog9
Exactly, see his comment on my answer - I think he is a bit lost...
Jason Bunting
The second assignment in the original question was confusing; I've removed this now. After `bar = { baz: "qqqq" }`, how can you arrange for `bar()` to be callable as a function?
mjs
You don't. You've just assigned an object to it which *IS NOT* a function - you can either start over (and assign a function to it), or you can get on with your life.
Shog9
Let me try to say this another way: you aren't naming a function "bar" any more than i'm naming 3 "three". You're just assigning a literal to a variable, and that variable can be re-assigned to anything else at any time. Perhaps your confusion comes out of a misunderstanding of the . operator?
Shog9
The question seems to make sense to me. Although he said 'assign a function the the variable', he seems to be asking (I'll use a bit of C++ terminology) how to assign a method operator() to his object. This does not seem to me a bad question, even if the answer's "no".
Steve Jessop
+6  A: 

There doesn't appear to be a standard way to do it, but this works.

WHY however, is the question.

function functionize( obj , func )
{ 
   out = func; 
   for( i in obj ){ out[i] = obj[i]; } ; 
   return out; 
}

x = { a: 1, b: 2 }; 
x = functionize( x , function(){ return "hello world"; } );
x()   ==> "hello world"

There is simply no other way to acheive this, doing

x={}
x()

WILL return a "type error". because "x" is an "object" and you can't change it. its about as sensible as trying to do

 x = 1
 x[50] = 5
 print x[50]

it won't work. 1 is an integer. integers don't have array methods. you can't make it.

Kent Fredric
A: 

Use a temporary variable:

var xxx = function()...

then copy all the properties from the original object:

for (var p in bar) { xxx[p] = bar[p]; }

finally reassign the new function with the old properties to the original variable:

bar = xxx;
Avner
+8  A: 

It's easy to be confused here, but you can't (easily or clearly or as far as I know) do what you want. Hopefully this will help clear things up.

First, every object in Javascript inherits from the Object object.

//these do the same thing
var foo = new Object();
var bar = {};

Second, functions ARE objects in Javascript. Specifically, they're a Function object. The Function object inherits from the Object object. Checkout the Function constructor

var foo = new Function();
var bar = function(){};
function baz(){};

Once you declare a variable to be an "Object" you can't (easily or clearly or as far as I know) convert it to a Function object. You'd need to declare a new Object of type Function (with the function constructor, assigning a variable an anonymous function etc.), and copy over any properties of methods from your old object.

Finally, anticipating a possible question, even once something is declared as a function, you can't (as far as I know) change the functionBody/source.

Alan Storm
just a side note, you can't change the source, but you CAN redefine the function (e.g. overwrite it) at any time.
scunliffe
A: 
var bar = { 
    baz: "qqqq",
    runFunc: function() {
        return 1;
    }
};

alert(bar.baz); // should produce qqqq
alert(bar.runFunc()); // should produce 1

I think you're looking for this.

can also be written like this:

function Bar() {
    this.baz = "qqqq";
    this.runFunc = function() {
        return 1;
    }
}

nBar = new Bar(); 

alert(nBar.baz); // should produce qqqq
alert(nBar.runFunc()); // should produce 1
JKempton