Javascript 如果类和对象之间没有区别,为什么';这个代码不起作用吗?
我一直被教导,在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() {
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-还没有,但是类
是一个,所以请继续关注!)