开发者

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

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 开发者_JAVA百科up with that?


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.


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.


I'd recommend reading https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/this, especially the section on "Function context".

In a nutshell, when you new function, you're creating a new object: var h = new f;

This says: "Create a new object referenced by the variable named h of type f". The function is then treated as a constructor rather than what you're expecting.

Once the object has been created, it's no longer callable (which is why you're experiencing an error on the line h().

In most language (Javascript not excluded), the () of a constructor are optional (unless there are required parameters (in some languages)).


Basically, the new keyword calls f as the constructor of a new object. The first reply to this question, on StackOverflow, sums it up quite nicely:

What is the 'new' keyword in JavaScript?


In JavaScript, functions aren't just functions, and they're not just objects; they're also used to defined constructors for types.

Generally speaking, when you have a function f, that function defines a type, whether that was intended or not. So the line

var h = new f();

defines an object h whose type is f.

I've never seen the line

var h = new f;

but I'm assuming it does the same as the other line.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜