繁体   English   中英

JavaScript从子对象调用父函数

[英]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(); ,有效发生的是以下几点:

  1. JavaScript创建一个新的空白对象,该原型等于您正在调用的函数的prototype -property。 在代码中,这将是var temp = Object.create(SuperClass.prototype);
  2. JavaScript使用该对象调用您的函数作为this对象。 在代码中,这将是SuperClass.call(temp, <arguments>)
  3. 如果函数返回任何内容,则将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 )。 通过返回自己的对象,你会错过更多的东西,例如能够使用instanceOfchildObj instanceOf childClass将为false )。

为了让所有的工作,你必须在方法分配给this构造函数中(而不是返回的对象)。 您可以在MDN文档中找到有关该OOP样式的更多信息。


注意:通常使用大写字母(即ChildClass来启动构造函数的名称。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM