无法移动使用 super 的方法

Can’t move a method that uses super

我正在阅读 this book。检查部分“15.6.4.2 陷阱:无法移动使用 super 的方法

内容如下

You can’t move a method that uses super: Such a method has the internal slot [[HomeObject]] that ties it to the object it was created in. If you move it via an assignment, it will continue to refer to the superproperties of the original object.

所以,我尝试用不同的对象调用它,并将实例方法分配给不同的对象,但它似乎不起作用。它指的是新对象的属性。可能,我没有正确理解作者的意思。那么,谁能举个例子?

她的是 small demo 和下面的代码

class A {
  get a() {
    return 1;
  }

  sayHi() {
    console.log(this.a)
  }
}

class B extends A {
  sayHi() {
    super.sayHi();
  };
}
var obj = {
  a: 4
};
let b = new B();
b.sayHi();
// logs 1

b.sayHi.call(obj);
// logs 4

obj.sayHi = b.sayHi;
obj.sayHi();
// logs 4

OP 表示 super.sayHi() 将始终调用 A.prototype.sayHi,无论您调用该方法的对象是什么。人们可能已经预料到

const sayHi = new B().sayHi; // or B.prototype.sayHi

const prototype = {
  sayHi() {
    console.log("not the a property");
  }
};
const myObject = Object.assign(Object.create(prototype), {
  a: "the a property"
});
myObject.sayHi = sayHi;
myObject.sayHi();
// or just sayHi.call(myObject);

不记录 a 属性 - 通过 myObject 的原型链调用 prototype.sayHi。但事实并非如此,它会正常记录 a 属性。

您的代码没问题,因为 this 在您移动方法时有效,但 super 无效(您的代码仅真正测试 this)。以下代码测试 super:

class Bird {
  getName() {
    return 'Bird';
  }
}
class Mammal {
  getName() {
    return 'Mammal';
  }
}
class Human extends Mammal {
  getName() {
    return super.getName();
  }
}
class Duck extends Bird {
}
// Moving method .getName() from Human.prototype to Duck.prototype
Duck.prototype.getName = Human.prototype.getName;

console.log(new Duck().getName()); // 'Mammal' (not 'Bird')

要了解结果,您需要了解 super 是如何工作的——它使用存储在方法本身中的内部 属性 [[HomeObject]],它不依赖于 this。也就是说,Human.prototype.getName() 内部工作方式如下:

Human.prototype.getName = Object.assign(
  function me() {
    return me.__HomeObject__.__proto__.getName();
  },
  { __HomeObject__: Human.prototype }
);

更多细节在book中解释: