如果类和对象之间没有区别,为什么这段代码不起作用?

时间:2013-04-19 20:46:53

标签: javascript function prototype

我总是被告知,在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 个答案:

答案 0 :(得分:4)

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

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

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

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

答案 1 :(得分:1)

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

firstObj.sayHi();

您正在尝试访问sayHi的{​​{1}}属性,这是一个firstObj对象,没有这样的属性。 (但你可以做Function。)

在第二种情况下:

firstObj.prototype.sayHi()

您首先在new firstObj().sayHi(); 对象上调用new运算符,该运算符计算为新对象。该新对象的firstObj属性为firstObj,原型等于constructor的{​​{1}}属性。然后,您正在访问该返回对象的prototype属性,该属性成功,因为firstObj位于该对象的原型链中。

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

2 但是,sayHifuture reserved word

答案 2 :(得分:0)

函数只是一个函数,直到new发出。此时,基于函数的原型创建Function 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();

答案 3 :(得分:0)

当你写这个:

var firstObj = function() {};

你只定义一个构造函数,因此你需要使用关键字new来创建用这个构造函数创建的新对象。