50

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?

5
  • I don't understand the need to do this. Can you give a concrete example of what you are trying to achieve? Commented Sep 23, 2008 at 22:40
  • 1
    I can't think of a use for the second form right now. The first is somewhat useful for static variables (though closures will also do). I'm mostly asking because I can't think of a way of achieving it without copying the properties across, which is unfortunate since they're parallel forms. Commented Sep 23, 2008 at 22:55
  • Sounds like you're hoping that because you can assign a method to a Javascript object, you can also assign an operator overload. I don't know Javascript so I don't know the answer, but good luck... Commented Sep 23, 2008 at 23:28
  • 7
    This seems a reasonable question, and I've found myself wanting to do it several times. Presumably one would need to change the prototype of the object from Object.prototype to Function.prototype. Perhaps it would be easier to create the function first and then transfer the object's properties across. Commented Mar 5, 2012 at 0:51
  • I used this to inherit a ko viewmodel ctr function from server side generated json object Commented Mar 13, 2014 at 21:49

9 Answers 9

30

You can't (as far as I know) do what you're asking, but hopefully this will clear up any confusion.

First, most objects in Javascript inherit from the Object prototype.

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

console.log(foo instanceof Object); // true
console.log(bar instanceof Object); // true

Second, functions ARE objects in Javascript. Specifically, they are objects that inherit from the Function prototype, which itself inherits from the Object prototype. Check out Function on MDN for more information.

// various ways of creating functions
var foo = new Function();
var bar = function(){};
function baz(){};

// all functions are Function objects, and therefore Object objects
console.log(foo instanceof Function); // true
console.log(foo instanceof Object);   // true

If you create a value that is an Object object first, you can't (as far as I know) convert it to a Function object later. What you CAN do however is create a new function, copy the properties from your old object to this function, and then reassign that function to the same variable, discarding the old object.

You can quickly copy the properties of one object to another with Object.assign(target, source).

var foo = { baz: "qqqq" };

var bar = function () { return 1; };  // create a new function
Object.assign(bar, foo);              // copy the properties of foo to it
foo = bar;                            // assign the function to foo

console.log(foo instanceof Function); // true
console.log(foo());                   // 1
console.log(foo.baz);                 // "qqqq"

But this isn't something you would typically do in practice. It's generally not recommended to add properties to a standard object like functions in the first place.

Finally, anticipating a possible question, you can't change the body of a function after it has been created. The function body is stored internally and not exposed as a property.

Sign up to request clarification or add additional context in comments.

3 Comments

just a side note, you can't change the source, but you CAN redefine the function (e.g. overwrite it) at any time.
All objects inherit from Object.prototype (if not explicitly set to another object). Function objects inherit from Function.prototype.
I always feel a bit awkward editing an answer by someone with much more rep than me, but I figured this old answer could use rephrasing to avoid confusion. Sorry about the wild diff, I got a bit carried away.
26

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.

2 Comments

Why this works isn't a mystery at all. You're just replacing x with the function.
Yeah, but this also copies all the properties of x onto the function before replacing x with the function. Though I think ( its been a few years since I answered this ) that the "Why" is more "A function is an object is a bit confusing"
4

Object types are functions and an object itself is a function instantiation.

alert([Array, Boolean, Date, Function, Number, Object, RegExp, String].join('\n\n'))

displays (in FireFox):

function Array() {
    [native code]
}

function Boolean() {
    [native code]
}

function Date() {
    [native code]
}

function Function() {
    [native code]
}

function Number() {
    [native code]
}

function Object() {
    [native code]
}

function RegExp() {
    [native code]
}

function String() {
    [native code]
}

In particular, note a Function object, function Function() { [native code] }, is defined as a recurrence relation (a recursive definition using itself).

Also, note that the answer 124402#124402 is incomplete regarding 1[50]=5. This DOES assign a property to a Number object and IS valid Javascript. Observe,

alert([
  [].prop="a",
  true.sna="fu",
  (new Date()).tar="fu",
  function(){}.fu="bar",
  123[40]=4,
  {}.forty=2,
  /(?:)/.forty2="life",
  "abc".def="ghi"
].join("\t"))

displays

a   fu  fu  bar 4   2   life    ghi

interpreting and executing correctly according to Javascript's "Rules of Engagement".

Of course there is always a wrinkle and manifest by =. An object is often "short-circuited" to its value instead of a full fledged entity when assigned to a variable. This is an issue with Boolean objects and boolean values.

Explicit object identification resolves this issue.

x=new Number(1);  x[50]=5;  alert(x[50]);

"Overloading" is quite a legitimate Javascript exercise and explicitly endorsed with mechanisms like prototyping though code obfuscation can be a hazard.

Final note:

alert(  123 . x = "not"  );

alert( (123). x = "Yes!" );  /* ()'s elevate to full object status */

1 Comment

(123).x = "TypeError" maybe you meant this instead (new Number(123)).x = "This works" or am I missing something?
1

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;

Comments

1
var A = function(foo) {                                                                                                      
  var B = function() {                                                                                                       
    return A.prototype.constructor.apply(B, arguments);
  };
  B.prototype = A.prototype;                                                                                                 
  return B;                                                                                                                  
}; 

1 Comment

What exactly is this doing?
1

NB: Post written in the style of how I solved the issue. I'm not 100% sure it is usable in the OP's case.

I found this post while looking for a way to convert objects created on the server and delivered to the client by JSON / ajax.

Which effectively left me in the same situation as the OP, an object that I wanted to be convert into a function so as to be able to create instances of it on the client.

In the end I came up with this, which is working (so far at least):

var parentObj = {}

parentObj.createFunc = function (model)
{
    // allow it to be instantiated
    parentObj[model._type] = function()
    {
        return (function (model)
        {
            // jQuery used to clone the model
            var that = $.extend(true, null, model);
            return that;
        })(model);
    }
}

Which can then be used like:

var data = { _type: "Example", foo: "bar" };
parentObject.createFunc(data);
var instance = new parentObject.Example();

In my case I actually wanted to have functions associated with the resulting object instances, and also be able to pass in parameters at the time of instantiating it.

So my code was:

var parentObj = {};
// base model contains client only stuff
parentObj.baseModel =
{
    parameter1: null,
    parameter2: null,
    parameterN: null, 
    func1: function ()
    {
        return this.parameter2;
    },
    func2: function (inParams) 
    {
        return this._variable2;
    }
}

// create a troop type
parentObj.createModel = function (data)
{
    var model = $.extend({}, parentObj.baseModel, data);
    // allow it to be instantiated
    parentObj[model._type] = function(parameter1, parameter2, parameterN)
    {
        return (function (model)
        {
            var that = $.extend(true, null, model);
            that.parameter1 = parameter1;
            that.parameter2 = parameter2;
            that.parameterN = parameterN;
            return that;
        })(model);
    }
}

And was called thus:

// models received from an AJAX call
var models = [
{ _type="Foo", _variable1: "FooVal", _variable2: "FooVal" },
{ _type="Bar", _variable1: "BarVal", _variable2: "BarVal" },
{ _type="FooBar", _variable1: "FooBarVal", _variable2: "FooBarVal" }
];

for(var i = 0; i < models.length; i++)
{
    parentObj.createFunc(models[i]);
}

And then they can be used:

var test1 = new parentObj.Foo(1,2,3);
var test2 = new parentObj.Bar("a","b","c");
var test3 = new parentObj.FooBar("x","y","z");

// test1.parameter1 == 1
// test1._variable1 == "FooVal"
// test1.func1() == 2

// test2.parameter2 == "a"
// test2._variable2 == "BarVal"
// test2.func2() == "BarVal"

// etc

Comments

1

Here's easiest way to do this that I've found:

let bar = { baz: "qqqq" };
bar = Object.assign(() => console.log("do something"), bar)

This uses Object.assign to concisely make copies of all the the properties of bar onto a function.

Alternatively you could use some proxy magic.

Comments

0

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";

4 Comments

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?
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.
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?
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".
-2
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

1 Comment

This does not touch on the original question at all, which was how to convert a plain object to a runnable function. Your answer simply assigns a function as a property of an object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.