我总是被告知,在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();
有什么区别?为什么不是第一个工作?
答案 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 但是,sayHi
是future 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
来创建用这个构造函数创建的新对象。