无法移动使用 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中解释:
我正在阅读 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中解释: