Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"newing" a function in JavaScript - what does it mean?

Tags:

javascript

Consider the following code:

var f = function() { return 10; }
typeof f;                         // returns "function"
f();                              // returns 10

var g = f;
g();                              // returns 10, obviously

var h = new f;
h;                                // console evaluates to f - ????
h();                              // Type error - called_non_callable
typeof h;                         // returns "object"

So, what is h here? The Chrome console seems to evaluate it as f, but it isn't callable. What does it mean to "new" a function like this? How is h now related to f?

As an aside, these two lines appear to be equivalent:

var h = new f;
var h = new f();

What's up with that?

like image 911
Mike Chamberlain Avatar asked Sep 08 '11 07:09

Mike Chamberlain


2 Answers

The root of your confusion is the way that Chrome represents objects on its console.

The expression new f() in your example is represented as 'f' on the Chrome's console output, but just as a mere "convenience" of this particular console, for example, logging the following object:

({constructor: function Foo(){}});

Will show it represented as "Foo". Basically the console tries to find a representation of which constructor your object is instance of.

So, the console shows you f, but you are not logging the function, the new operator produces an object that inherits from f.prototype.

You are returning 10 from the function, but since you call it with new, and the return type is a primitive, the value is discarded, the newly created object that inherits form f.prototype is returned.

For example:

var F = function () { return 10; };
F.prototype.inherited = 'foo';

var h = new F(); // the 10 returned is ignored
h instanceof F; // true
h.inherited;    // "foo"

On the other hand, if you return an object from a constructor, the object instance that the new operator creates behind the scened (and inherits from the constructor's prototype) will be lost, for example:

var F = function () { return  {}; };
F.prototype.inherited = 'foo';

var h = new F(); // the empty object is returned
h instanceof F; // false
h.inherited;    // undefined

Yes, new f; and new f(); are completely equivalent, although people recommend using the parentheses to add clarity to your code.

like image 105
Christian C. Salvadó Avatar answered Sep 20 '22 18:09

Christian C. Salvadó


this is how object-orientation in JavaScript works. if you call new on a function, this function would be treated as if it's a constructor of a class (the keywords class to define a class like other languages do doesn't exist in js).

so calling var h = new f(); makes h an object of class f, and an object itself isn't callable (that's why you get called_non_callable).

if you want to give your "class" some methots, you should do it like this:

function cat(name) {
    this.name = name;
    this.talk = function() {
        alert( this.name + " says meeow!" )
    }
} 

cat1 = new cat("felix")
cat1.talk() //alerts "felix says meeow!"

cat2 = new cat("ginger")
cat2.talk() //alerts "ginger says meeow!"

that's an example from page 2 of this tutorial. for more information, read that or ask Google for object-orientation in JavaScript.

like image 43
oezi Avatar answered Sep 23 '22 18:09

oezi