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.
精彩评论