3

我总是被教导在 Javascript 中对象和类之间没有区别。然后有人可以解释为什么这段代码会产生错误:

var firstObj = function() {};

firstObj.prototype.sayHi = function() {
document.write("Hi!");
};

firstObj.sayHi();

而这个有效:

var firstObj = function() {};

firstObj.prototype.sayHi = function() {
document.write("Hi!");
};

new firstObj().sayHi();

有什么不同?为什么第一个不起作用?

4

4 回答 4

4

这里的关键问题是你的firstObj变量是一个Function对象,而不是一个firstObj对象。这是一个微妙的区别,但对象的类型决定了它继承的原型。

原型就像一个模板,应用于新创建的特定类型的对象。您必须创建一个firstObj对象(通常使用new它调用构造函数并分配原型)才能将该模板应用于它。在第一个示例中,您的firstObj变量是一个Function对象,而不是一个firstObj对象,因此它的原型Function不是其他任何东西..

在您的第二个示例中,您实际上创建了一个firstObj对象,因此它继承了该类型对象的原型。

如果您希望在第一个示例中应用该方法,以便它适用于您已经创建的函数对象,只需将该方法直接放在您已经存在的函数对象上,而不是原型上。

于 2013-04-19T20:48:50.187 回答
1

对象和类之间的语言没有区别1。但是,一种对象与另一种对象之间存在很大差异。在第一种情况下:

firstObj.sayHi();

您正在尝试访问 的sayHi属性firstObj,这是一个Function没有此类属性的对象。(但是,您可以这样做firstObj.prototype.sayHi()。)

在第二种情况下:

new firstObj().sayHi();

您首先new在对象上调用运算符,该运算符firstObj计算为一个新对象。该新对象具有firstObj其属性和与 的属性constructor相等的原型。然后,您正在访问该返回对象的属性,该属性成功,因为它位于该对象的原型链中。prototypefirstObjsayHisayHi

1从技术上讲,JavaScript 没有类2(传统意义上的),只有通常称为“类”的构造函数。

2然而,class是一个未来的保留字

于 2013-04-19T20:52:23.303 回答
0

一个函数只是一个函数,直到new被发出。此时,aFunction Object基于函数的原型创建。这就是为什么您不会sayHi在第一个版本中看到该方法。

此外,firstObj它是一个函数,而不是一个对象,因此您需要调用它才能真正发生任何事情。firstObj不会实际调用该函数,您必须使用firstObj().

此外,还有一些方法可以在不明确要求new关键字的情况下使用原型。这是在许多流行的框架(例如 jQuery)中完成的。它是通过检查是否new被使用来完成的,如果没有,那么它new会当场为你准备好:

jsFiddle Demo

var firstObj = function() {
 if( !(this instanceof firstObj) ){
  return new firstObj();   
 }
};

firstObj.prototype.sayHi = function() {
 alert("hi");
};

firstObj().sayHi();
于 2013-04-19T20:50:06.363 回答
0

当你写这个:

var firstObj = function() {};

您只定义了一个构造函数,因此您需要为使用此构造函数创建的新对象使用关键字new

于 2013-04-19T20:50:32.317 回答