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

Javascript 如果类和对象之间没有区别,为什么';这个代码不起作用吗?,javascript,function,prototype,Javascript,Function,Prototype,我一直被教导,在Javascript中,对象和类之间没有区别。那么有人能解释一下为什么这段代码会产生错误: var firstObj = function() {}; firstObj.prototype.sayHi = function() { document.write("Hi!"); }; firstObj.sayHi(); 鉴于这一点有效: var firstObj = function() {}; firstObj.prototype.sayHi = function() {

我一直被教导,在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();

有什么区别?为什么第一个不能工作?

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

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

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


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

函数只是一个函数,直到发布
new
。此时,将基于函数的原型创建一个
函数对象
。这就是为什么在第一个版本中不会看到
sayHi
方法的原因

而且,
firstObj
是一个函数,而不是一个对象,因此您需要调用它来实际执行任何操作
firstObj
不会实际调用函数,必须使用
firstObj()

此外,还有一些方法可以在不明确要求
new
关键字的情况下使用原型。这是在许多流行的框架(如jQuery)中完成的。检查是否使用了
new
,如果未使用,则现场为您准备一个
new

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

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

firstObj().sayHi();
当你写这篇文章时:

var firstObj = function() {};
您只定义了一个构造函数,因此需要使用关键字
new
来表示使用此构造函数创建的新对象。

对象和类之间的语言没有区别1。然而,一种物体和另一种物体之间有很大的区别。在第一种情况下:

firstObj.sayHi();
您正试图访问
firstObj
sayHi
属性,该属性是一个
函数
对象,它没有这样的属性。(但是,您可以执行
firstObj.prototype.sayHi()

在第二种情况下:

new firstObj().sayHi();
首先调用
firstObj
对象上的
new
操作符,该操作符的计算结果为一个新对象。该新对象的
firstObj
属性与
firstObj
prototype
属性相同。然后访问该返回对象的
sayHi
属性,该属性成功,因为
sayHi
位于该对象的原型链中

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


2然而,
是a.

在第一个示例中,定义了firstObj.prototype.sayHi。那么,当调用firstObj.sayHi()时,为什么js引擎不“沿着原型”链走一走并找到对它的引用?@sshen-因为
firstObj
只是一个函数对象。它不是
firstObj
对象。您必须实际创建一个
firstObj
对象来继承原型。这充其量只是误导
firstObj
Function
的一个实例(即
firstObj.prototype===Function
)。而
Function
实例无疑是对象。另外,
(new firstObj).sayHi()
(在
firstObj
之后没有括号)的工作原理与OP的第二个代码一样好。之所以需要paren,是因为否则它将被评估为
new((firstObj.sayHi)()
。我想你误解了我在说
函数对象时的意思。
函数
实例是一个对象。但是,
firstObj.prototype==Function
为false。此外,
typeofnewfirstobj===object
typeoffirstobj===function
。以这种方式使用括号会导致
newfirstobj
成为一个表达式,这就是为什么它会起作用<代码>变量fO=新的第一个对象;fO.sayHi()
将是另一种看待这个问题的方式。使用
new
时,不需要调用函数,它是隐式的。是的,我对
firstObj.prototype
的理解是错误的;我的意思是
firstObj
(不是
prototype
属性)的原型是
Function
firstObj instanceof Function
true
)。因此,作为
函数
对象的是
firstObj
,而不是
newfirstobj
。(
(new firstObj())instanceof Function
false
,正如
(new firstObj)instanceof Function
一样)您的第二段还有其他误导性信息:JavaScript中的所有函数实际上都是对象(
firstObj instanceof Object
也是
true
)。(毕竟,这就是为什么它可以有一个
原型
属性。)类在javascript中不存在…@jondavidjohn-还没有,但是
是一个,所以请继续关注!)