[英]JavaScript call parent function from child object
我是javascript的面向对象编程的新手。 并尝试实现我们从其他编程语言中了解的基础知识。
我有两个班,一个家长和一个孩子。 父母有一些私人功能和一些公共功能。 Child将继承父类。
我希望从子对象访问父公共函数。 我想做什么:
function SuperClass {
//Constructor implementation of this class
//public functions
return {
parentPublicFunction: function() {
//Public function implementation
}
}
function privateFunction() {
//Private function implementation.
}
}
//Inheriting
childClass.prototype = Object.create(SuperClass.prototype);
childClass.prototype.constructor = childClass;
childClass.prototype.parent = SuperClass.prototype;
function childClass {
//Call to super constructor
this.parent.constructor.call(this, arguments);
//Public function for childClass.
return {
childPublicFunction: function() {
//function implementation
}
}
}
var childObj = new childClass();
childObj.parentPublicFunction();
我在运行时收到此错误:
未捕获的TypeError:undefined不是函数
我做的是不正确的事吗? 提前致谢!
JavaScript OOP不像Java或C#那样工作,不要指望它,也不要尝试制作它。 这样做的唯一原因是误解。 而不是试图强制你的旧范式完全不同的语言,而是学习JavaScript OOP的工作原理。
JavaScript是面向对象的,但这并不意味着它有类。 至少不是大多数来自Java或类似语言的开发人员都会想到类。 它也没有经典继承。 但是,所有这些都可以“伪造”或模仿(这是你有效地尝试做的)。 这样做的问题是,来自Java或类似的开发人员看到类似于类和经典继承的代码,因此他们认为它是具有经典继承的类,并期望它表现得如此,而它可能最终完全工作不同。
让我们从你的SuperClass
函数开始(因为它就是它。它是一个函数,而不是一个类)。 首先,您的代码甚至不是有效的语法,因为您的SuperClass
函数没有括号。 正确的语法是function SuperClass() { ... }
。
其次,JavaScript使用原型来处理对象(而不是类)之间的继承,如果你想做原型继承(你的一些代码建议你想要),你就不能从SuperClass
函数返回一个新的匿名对象。 请允许我说明一下这里发生了什么。
使用new
关键字调用SuperClass
函数(来自childClass
函数或来自任何其他地方)时,如var inst = new SuperClass();
,有效发生的是以下几点:
prototype
-property。 在代码中,这将是var temp = Object.create(SuperClass.prototype);
。 this
对象。 在代码中,这将是SuperClass.call(temp, <arguments>)
。 inst
设置为该值,否则将其设置为temp
值。 现在,在您的SuperClass
函数中,您执行以下操作:
//Constructor implementation of this class
//public functions
return {
parentPublicFunction: function() {
//Public function implementation
}
}
function privateFunction() {
//Private function implementation.
}
这里发生的是,你的SuperClass
方法得到的以调用this
,这是一个实例SuperClass
,即。 它的原型链中有SuperClass.prototype
。 这意味着,如果您this instanceof SuperClass
,那么您将会如您所料那样成为true
。 然后你去返回一个新的匿名对象,它有一个名为parentPublicFunction
的属性(恰好是一个函数,但可以是任何东西)。 您返回的这个新对象不是SuperClass
的实例。 它的属性中没有SuperClass.prototype
。 您已经创建了一种情况,如果我这样做(new SuperClass()) instanceof SuperClass
您就会得到错误。 换句话说,从SuperClass
构造函数返回的实例不会实现您的“类”。 这可能完全不是你想要的,这也是你不能仅仅在JavaScript上使用经典继承原则并期望事物运行相同的原因之一。
现在,我们到目前为止,是一个函数名称SuperClass
,它返回一个与SuperClass
没有任何关系的Object
。 SuperClass
有一个空的原型,这意味着即使你以某种方式设法在其原型链中创建具有SuperClass.prototype
对象,它也不会从SuperClass
继承任何东西,因为没有任何定义可以继承。 这将我们带到了childClass
函数。
首先,我将命名为ChildClass
而不是childClass
。 您期望人们使用new
调用的JavaScript中的任何函数都应以大写字母开头。 您不希望使用new
调用的任何函数都应以小写字母开头。 在JavaScript中无法知道函数是否打算使用或不使用new
来调用,因此这用于表示。
现在, ChildClass.prototype
被设置为SuperClass
一个实例,这意味着SuperClass
原型中的任何方法都可以从ChildClass
的实例中调用。 而ChildClass
任何实例也是SuperClass
一个实例(就像你期望的那样)。 但是,正如已经解释过的那样, SuperClass
的原型是空的,所以没有什么可以继承它。 因此, ChildClass
从此继承中获得的唯一事实是a instanceof ChildClass
意味着a instanceof SuperClass
。 但是,就像在SuperClass
,您从ChildClass
返回一个匿名对象,这又导致(new ChildClass()) instanceof ChildClass
为false。
其中,存在(大多数)你的问题。 解决方案只是为了了解OOP如何在JavaScript中运行并在执行JavaScript时接受它,而不是试图将其弯曲到您认为工作的方式。
因为要从构造函数返回自己的对象,所以必须多做一些管道。
//Call to super constructor
this.parent.constructor.call(this, arguments);
返回SuperClass
的公共API,但是你没有对结果做任何事情。 你必须将它合并到孩子的公共API中:
//Call to super constructor
var parentAPI = this.parent.constructor.call(this, arguments);
//Public function for childClass.
return Object.assign(parentAPI, {
childPublicFunction: function() {
//function implementation
}
});
在您的情况下,分配给childClass.prototype
实际上是无关紧要的,因为从构造函数返回的对象无论如何都不会从它继承。 即childObj
将不具有您分配给原型的任何属性(例如parent
)。 通过返回自己的对象,你会错过更多的东西,例如能够使用instanceOf
( childObj instanceOf childClass
将为false
)。
为了让所有的工作,你必须在方法分配给this
构造函数中(而不是返回的对象)。 您可以在MDN文档中找到有关该OOP样式的更多信息。
注意:通常使用大写字母(即ChildClass
来启动构造函数的名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.