我有以下 JavaScript 类,位于 onClick
中Lesson
的方法类 lessonObj
属性未定义,但 init
Lesson
的方法类被正确调用。我该如何更改代码才能使其正常工作?
谢谢
class Item
{
name;
constructor(name)
{
this.name = name;
}
}
class Page
{
pageObj;
constructor()
{
this.init();
}
init()
{
this.pageObj = new Item('John');
}
}
class Lesson extends Page
{
lessonObj;
constructor()
{
super();
}
onClick(event)
{
alert(this.pageObj.name);
alert(this.lessonObj.name);
}
init()
{
super.init();
this.lessonObj = new Item('Mary');
document.addEventListener('click', event => this.onClick(event));
}
}
new Lesson();
Click somewhere
最佳答案
这里是这一行:
class Lesson extends Page
{
lessonObj; // <<<<<<<<<
constructor()
{
super();
}
该行基本上添加了 this.lessonObj = undefined
到super()
之后的构造函数在任何其他代码之前调用。
所以整体的执行顺序是这样的:
class Page {
5. pageObj;
4. constructor() {
5. //this.pageObj = undefined;
6. this.init();
}
11. init() {
12. this.pageObj = new Item('John');
}
}
class Lesson extends Page {
13. lessonObj;
2. constructor() {
3. super();
13. //this.lessonObj = undefined;
}
later onClick(event) {
alert(this.pageObj.name);
alert(this.lessonObj.name);
}
7. init() {
8. this.lessonObj = new Item('Mary');
9. document.addEventListener('click', event => this.onClick(event));
10. super.init();
}
}
1. new Lesson();
这样this.lessonObj = new Item('Mary');
来自init()
随后被 this.lessonObj = undefined;
覆盖在 constructor()
.
这就是为什么当您进入点击处理程序时,this.lessonObj
为空。
这里是执行 const me = new Lesson();
时执行的代码的概要(按正确的顺序) 。自从我内联了函数调用的内容以来,我已经注释掉了它们。
const me = {};
Object.setPrototypeOf(me, Lesson.prototype);
// Lesson.prototype.constructor.call(me);
// Page.prototype.constructor.call(me);
me.pageObj = undefined;
// Lesson.prototype.init.call(me);
me.lessonObj = new Item('Mary');
document.addEventListener('click', event => me.onClick(event));
// Page.prototype.init.call(me);
me.pageObj = new Item('John');
me.lessonObj = undefined;
What is now the best practice to solve that?
对此没有唯一的解决方案。
class Lesson extends Page {
lessonObj;
constructor() {
super();
this.lessonObj = new Item('Mary');
document.addEventListener('click', event => this.onClick(event));
}
onClick(event) {
alert(this.pageObj.name);
alert(this.lessonObj.name);
}
}
甚至这个
class Page {
pageObj = new Item('John');
}
class Lesson extends Page {
lessonObj = new Item('Mary');
constructor() {
document.addEventListener('click', event => this.onClick(event));
}
onClick(event) {
alert(this.pageObj.name);
alert(this.lessonObj.name);
}
}
new Lesson();
或者如果您想保留init()
但要确保init()
在所有构造函数之后调用,您可以使用工厂函数:
class Item
{
name;
constructor(name)
{
this.name = name;
}
}
class Page {
static create() {
// in here, `this` points to the current constructor()
const instance = new this();
instance.init();
return instance;
}
pageObj;
init() {
this.pageObj = new Item('John');
}
}
class Lesson extends Page {
lessonObj;
onClick(event) {
console.log(this.pageObj.name);
console.log(this.lessonObj.name);
}
init() {
super.init();
this.lessonObj = new Item('Mary');
document.addEventListener('click', event => this.onClick(event));
}
}
const instance = Lesson.create();
console.log("instance", instance);
或者您可以选择 fluid interface
方法,让init()
总是return this
并写一些类似的内容
class Item
{
name;
constructor(name)
{
this.name = name;
}
}
class Page {
pageObj;
init() {
this.pageObj = new Item('John');
return this;
}
}
class Lesson extends Page {
lessonObj;
onClick(event) {
console.log(this.pageObj.name);
console.log(this.lessonObj.name);
}
init() {
super.init();
this.lessonObj = new Item('Mary');
document.addEventListener('click', event => this.onClick(event));
return this;
}
}
const instance = new Lesson().init();
console.log("instance", instance);
关于javascript - 这在 JavaScript 子类中不可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76199007/