“newing”JavaScript中的一个函数 - 它是什么意思?

时间:2011-09-08 07:37:34

标签: javascript

请考虑以下代码:

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"

那么,这里有什么? Chrome控制台似乎将其评估为f,但它不可调用。 “新”这样的功能意味着什么?现在如何与f相关?

顺便说一下,这两行看起来是等价的:

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

这是怎么回事?

5 个答案:

答案 0 :(得分:4)

这就是JavaScript中面向对象的方式。如果你在一个函数上调用new,这个函数将被视为它是一个类的构造函数(关键字class来定义一个类,就像其他语言在js中不存在一样)。 / p>

所以调用var h = new f();会使h成为类f的对象,并且对象本身不可调用(这就是为什么你得到called_non_callable)。

如果你想给你的“课堂”一些mehots,你应该这样做:

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

这是来自page 2this tutorial的示例。有关更多信息,请阅读或ask Google for object-orientation in JavaScript

答案 1 :(得分:4)

您混淆的根源是Chrome在其控制台上表示对象的方式。

您示例中的表达式new f()在Chrome的控制台输出中表示为“f”,但仅作为此特定控制台的“便利”,例如,记录以下对象:

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

将其显示为“Foo”。基本上,控制台试图找到表示,其构造函数对象是 的实例。

因此,控制台会向您显示f,但您没有记录该函数,new运算符会生成一个继承自f.prototype的对象。

您正在从函数返回10,但由于您使用new调用它,并且返回类型是原语,因此将丢弃该值,新创建返回继承表单f.prototype的对象。

例如:

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"

另一方面,如果从构造函数返回一个对象,new运算符在scened后面创建的对象实例(并继承自构造函数的原型)将丢失,例如:

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

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

是的,new f;new f();完全相同,但人们建议使用括号来增加代码的清晰度。

答案 2 :(得分:2)

我建议阅读https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/this,尤其是关于“功能背景”的部分。

简而言之,当您new运行时,您正在创建一个新对象: var h = new f;

这说:“创建一个名为h的{​​{1}}变量引用的新对象”。然后将该函数视为构造函数而不是您期望的那样。

创建对象后,它就不再可调用了(这就是为什么你在行f上遇到错误的原因。

在大多数语言中(不排除Javascript),构造函数的h()是可选的(除非有必要的参数(在某些语言中))。

答案 3 :(得分:1)

基本上,new关键字将f调用为新对象的构造函数。在StackOverflow上对这个问题的第一个回答总结得非常好:

What is the 'new' keyword in JavaScript?

答案 4 :(得分:1)

在JavaScript中,函数不仅仅是函数,它们不仅仅是对象;它们也用于定义类型的构造函数。

一般来说,当你有一个函数f时,该函数定义一个类型,无论是否有意。这一行

var h = new f();

定义了一个类型为h的对象f

我从未见过该行

var h = new f;

但我假设它和另一行一样。