javascript - JS 继承 : calling the parent's function from within the child's function

标签 javascript oop inheritance prototype

JS对象模型肯定有不明白的地方。

来自这些资源:

我收集了我认为或认为是对象模型的准确心理表征。在这里:


所有对象都有一个属性,文档将其称为[[Prototype]][[Prototype]] 可以被认为是对对象父对象的引用。更准确地说:

The reference to the [parent's] prototype object is copied to the internal [[Prototype]] property of the new instance. (source 1)

您可以使用 Object.getPrototypeOf(child) 访问子项的 [[Prototype]] 属性。此处返回的值将是对父项的引用原型(prototype)(不是它的内部 [[Prototype]] 属性,而是它的实际原型(prototype))

obj.prototype 不同于对象的内部 [[Prototype]] 属性。它就像用于创建此对象实例的蓝图,而其 [[Prototype]] 属性指向用于创建其父对象实例的蓝图。

  • Parent.prototype === Object.getPrototypeOf(child);//真

详细说明:

  • 如果您向 child.prototype 添加一个函数,该函数将可用于 child 及其任何子级。

  • 如果给parent.prototype加一个函数,相当于给Object.getPrototypeOf(child)加一个函数,那么这个函数就是可供 parent 及其所有子级使用,其中包括 child 及其所有 siblings

您可以使用 Object.create()使用您想要的任何 [[Protoype]] 属性创建一个新对象。所以你可以用它作为实现继承的一种方式。参见 source 2举个例子。


考虑到这一点,我想获得一个我自己的工作示例。我的计划是创建一个父“类”,然后创建一个继承自它的子“类”。

我想让子类实现一个方法,该方法重载了父类的一个方法。需要注意的是,我希望子版本的方法调用父版本的方法,然后做一些额外的事情。

这是我想出的,请参阅下面的相关问题:

var Parent = function() {};

Parent.prototype.myF = function() {
  console.log('derp');
};


function Child() {
  Parent.call(this);
};

//make [[prototype]] of Child be a ref to Parent.prototype
Child.prototype = Object.create(Parent.prototype);

//need to explicitly set the constructor
Child.prototype.constructor = Child;

Child.prototype.myF = function() {
  Object.getPrototypeOf(this).myF();
  console.log("did I derp??");
};

childInstance = new Child();
childInstance.myF();

情况似乎是,当我尝试重载 Parent.myF() 时,在重载它的同时,我实际上同时修改了原始函数。这似乎是因为记录的结果是:

'derp'
'did I derp??'
'did I derp??'

大概 'did I derp??' 的第一次出现来自父函数的修改版本,我有意这样做,然后第二个版本来自 child 的功能。

谁能详细说明为什么会这样?

最佳答案

好问题,需要一些测试和研究才能找到答案。

识别异常行为

我稍微更改了您的代码以找出在以下情况下调用了哪个函数:

var Parent = function() {};

Parent.prototype.myF = function() {
  console.log('derp');
};


function Child() {
  Parent.call(this);
  this.name = 'Test'; // this is a new test property
};

//make [[prototype]] of Child be a ref to Parent.prototype
Child.prototype = Object.create(Parent.prototype);

//need to explicitly set the constructor
Child.prototype.constructor = Child;

Child.prototype.myF = function() {
  console.log(this); // here I want to find out the context, because you use it in the next line
  Object.getPrototypeOf(this).myF();
  console.log("did I derp??");
};

childInstance = new Child();
childInstance.myF();

您可以查看 JSFiddle 并亲自尝试:http://jsfiddle.net/Lpxq78bs/

代码中的关键行是:

Child.prototype.myF = function() {
  Object.getPrototypeOf(this).myF(); // this one
  console.log("did I derp??");
};

在做了 console.log(this); 之后找出什么this指的是,我看到它在 did I derp?? 的第一个和第二个输出之间变化.

我得到了以下输出:

Object { name: "Test" }
Object { constructor: Child(), myF: window.onload/Child.prototype.myF() }
"derp"
"did I derp??"
"did I derp??"

解释输出

因为我在 Child 中添加了一个“名称”属性构造函数,它只会在我查看 Child 的实例时出现, 不在其 .prototype .

所以输出的第一行表示当前this上下文确实是 childInstance . 但第二个既不是childInstance ,也不是 Parent.prototype :

  1. 调用( myFchildInstance ):this指的是childInstance . Object.getPrototypeOf(this).myF();然后寻找 [[Prototype]]childInstance , 这是Child.prototype , 而不是 Parent.prototype 。 输出:“我有错吗??”

  2. 调用( myFChild.prototype ):this指的是Child.prototype ,这是 childInstances [[原型(prototype)]] 属性。所以第二次调用Object.getPrototypeOf(this).myF();最后返回 Parent.prototype (有点)。输出:“我有错吗??”

  3. 调用(由 myF 创建的 Parent.prototype 实例的 Object.create ):最后, myF在 parent 身上被称为。输出:'derp'

由于您的 console.log("did I derp??")myF 之后函数调用,输出顺序相反。下图说明了代码是如何遍历的:

enter image description here

所以你的假设是什么Object.getPrototypeOf(this).myF();指的是错的。

ES5 中的解决方案

来自@LukeP: https://jsfiddle.net/Lpxq78bs/28/

ES6 中的替代解决方案

为了避免这种混淆,并且由于您使用的是经典继承模式,您可以查看 ES6 Classes .以下是您正在尝试做的事情的粗略示例:

class Parent {
    constructor() {
      
    }
    
    myF() {
        console.log('derp');
    }
}

class Child extends Parent {
    constructor() {
        super();
    }

    myF() {
        super.myF();
        console.log("did I derp??");
    }
}

var childInstance = new Child();
childInstance.myF();

我希望这有助于理解发生了什么。

关于javascript - JS 继承 : calling the parent's function from within the child's function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30401967/

相关文章:

javascript - 图像未加载或未出现在元素源中

javascript - 不要以名称 IS 为目标,而是以随 jquery 递增的 ID 为目标

python - PyLint W0231 super-init-not-called with __init__ of 祖 parent

Javascript 继承并丢失 'this' 的上下文

matlab - MATLAB 中 x = f(x) 形式的函数调用的内存分配

c++ - std::find 用于继承对象 C++

javascript - 如何在 Office JavaScript 加载项中调用 .NET dll?

javascript - 根据数组中的对象属性生成带头的列表

java - 仅当子类强制转换为父类时才调用子类的方法?

Java 程序设计布局建议?