JavaScript 从 child object 调用 parent 函数

JavaScript call parent function from child object

我是 Object 面向 javascript 的编程新手。并尝试实现我们从其他编程语言中了解的基础知识。

我有两个 class,一个 parent 和一个 child。 Parent 有一些私有函数和一些 public 函数。 Child 将继承 parent class.

并且我希望从 child object 访问 parent public 函数。我想做什么:

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();

我在 运行 时遇到此错误:

Uncaught TypeError: undefined is not a function

我是不是做错了什么?提前致谢!

因为您要从构造函数中 return 构建自己的 object,所以您必须做更多的管道工作。

//Call to super constructor
this.parent.constructor.call(this, arguments);

return 是 SuperClass 的 public API,但您没有对结果做任何事情。您必须将其合并到 child 的 public 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 实际上与您的情况无关,因为构造函数中的 object 您 return 无论如何都不会继承它。 IE。 childObj 不会具有您分配给原型的任何属性(例如 parent)。 return 使用自己的 object 会错过更多的东西,例如能够使用 instanceOfchildObj instanceOf childClass 将是 false)。

为了完成所有这些工作,您必须在构造函数中将方法分配给 this(而不是 returning 一个 object)。您可以在 MDN documentation.

中找到有关这种 OOP 风格的更多信息

注意:构造函数的名称一般以大写字母开头,即ChildClass.

JavaScript OOP 不像 Java 或 C# 那样工作,不要指望它,也不要尝试实现它。这样做只会造成误解。与其尝试将旧范例强加于完全不同的语言,不如学习 JavaScript OOP 的工作原理。

Java脚本是面向对象的,但这并不意味着它有 classes。至少不是大多数来自 Java 或类似语言的开发人员认为 classes 的方式。它也没有 classical 继承。但是,所有这些都可以是 "faked" 或模仿的(这是您有效地尝试做的事情)。这样做的问题是,来自 Java 或类似的开发人员看到的代码看起来像 classes 和 classical 继承,所以他们认为它是 classes具有 classical 继承,并期望它的行为如此,而它最终可能会完全不同。

让我们从您的 SuperClass 函数开始(因为它就是这样。它是一个函数,而不是 class)。首先,您的代码甚至不是有效的语法,因为您的 SuperClass 函数没有括号。正确的语法是 function SuperClass() { ... }.

其次,Java脚本使用原型来处理对象之间的继承(不是 classes),如果您想进行原型继承(您的某些代码建议您这样做),您不能 return 来自 SuperClass 函数的新的匿名对象。请允许我稍微说明一下这里发生的事情。

当您使用 new 关键字调用 SuperClass 函数(从 childClass 函数或任何其他地方调用)时,如 var inst = new SuperClass();,什么有效发生如下:

  1. Java脚本创建一个新的空白对象,其原型等于您正在调用的函数上的 prototype-属性。在代码中,这将是 var temp = Object.create(SuperClass.prototype);.
  2. Java脚本使用该对象作为 this 对象调用您的函数。在代码中,这将是 SuperClass.call(temp, <arguments>).
  3. 如果函数 return 有任何内容,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,正如您所期望的那样。然后你去return一个新的匿名对象,它有一个名为parentPublicFunction的属性(它恰好是一个函数,但可以是任何东西)。您 return 的这个新对象不是 SuperClass 的实例。它的 属性 中没有 SuperClass.prototype。你创造了一种情况,如果我这样做 (new SuperClass()) instanceof SuperClass 你就会出错。换句话说,您 return 来自 SuperClass 构造函数的实例不会实现您的 "class"。这可能根本不是您想要的,这也是您不能仅将 class 逻辑继承原则捆绑在 Java 脚本上并期望事情具有相同功能的原因之一。

现在,到目前为止,我们有一个函数名 SuperClass,return 是一个 Object,与 SuperClass 没有任何关系。 SuperClass 有一个空的原型,这意味着即使你设法在它的原型链中创建带有 SuperClass.prototype 的对象,它也不会从 SuperClass 继承任何东西,因为没有任何东西定义为继承。这将我们带到 childClass 函数。

首先,我将其命名为 ChildClass 而不是 childClass。 JavaScript 中您希望人们使用 new 调用的任何函数都应以大写字母开头。任何您不希望使用 new 调用的函数都应以小写字母开头。在 Java 脚本中无法知道一个函数是否打算在有或没有 new 的情况下被调用,所以这被用来表示。

现在,ChildClass.prototype 被设置为 SuperClass 的实例,这意味着 SuperClass 原型中的任何方法都可以从 ChildClass 的实例中调用. ChildClass 的任何实例也是 SuperClass 的实例(正如您所期望的那样)。然而,正如已经解释过的,SuperClass 的原型是空的,因此没有任何东西可以从它继承。因此,ChildClass 从这种继承中获得的唯一好处是 a instanceof ChildClass 意味着 a instanceof SuperClass。但是,就像 SuperClass 一样,您 return 来自 ChildClass 的匿名对象,这再次导致 (new ChildClass()) instanceof ChildClass 为假。

你的(大部分)问题就在这里。解决方案很简单,就是了解 OOP 在 JavaScript 中的工作原理,并在执行 JavaScript 时拥抱它,而不是试图将其弯曲成您假设的工作方式。