为什么 `super` 关键字 属性 returns 在 ES6 class 中未定义?

Why does `super` keyword property returns undefined in an ES6 class?

我是 ES6 classes 的新手,正在尝试了解继承在其中的工作原理。我像这样创建了一个父 class Modal 和一个子 class ChildModal

class Modal {
    constructor(selector, document) {
        this.selector = selector;
        this.document = document;
    }

    get title() {
        return this._title;
    }

    set title(title) {
        if(!title) {
            throw new Error('Original title cannot be empty');
        }
        this._title = title;
    }

    defineNewTitle(newContent) {
        this.title = newContent + this.title;
    } 

    assignNewTitle() {
        $(this.selector).text(this.title);
    }
}

var modal = new Modal("#mainTitle");

modal.title = "Standards";

modal.defineNewTitle("JavaScript ");

modal.assignNewTitle();

class ChildModal extends Modal {
    constructor(selector, title) {
        super(selector, title);
    }

    defineChildTitle(title) {
        this.title = title + this.title;
    }

    assignChildTitle() {
        $(this.selector).text(this.title);
    }
}

var child = new ChildModal("#childTitle");
child.defineChildTitle("Wow ");
child.assignChildTitle();
<!DOCTYPE html>
<html>
<head>
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
 <title>Class test</title>
 <h1 id="mainTitle">
  Main title
 </h1>
 <h2 id="childTitle">
  Child title
</head>
<body>
 <script src="Modal.js"></script>
</body>
</html>

我希望 h2 标签被修改为 'Wow JavaScript Standards',但它却输出 'Wow undefined'。为什么在方法 defineChildTitle 中它不识别 this.titlechildModalclass中的思想,this.title应该是'JavaScriptStandardas I've inherited theModalclass in the constructor?enter code here`

您需要在构造函数中定义_title

class Modal {
    constructor(selector, document) {
        this.selector = selector;
        this.document = document;
        this._title = ''
    }
}

var child = new ChildModal("#childTitle");
child.title = "JavaScript Standards"
child.defineChildTitle("Wow ");
child.assignChildTitle();

您目前正在加入 stringundefined,结果是 undefined

由于您正在创建两个实例,它们彼此不相关,因此 child.titlemodal.title 不同,因此将两者连接会产生两个不同的字符串。

因此,您不仅需要在 modal.title = 'JavaScript Standards' 中设置标题,而且还必须在 child.title = 'JavaScript Standards' 中设置相同的内容。

class Modal {
    constructor(selector, document) {
        this.selector = selector;
        this.document = document;
        this.title = ' '
    }

    get title() {
        return this._title;
    }

    set title(title) {
        if(!title) {
            throw new Error('Original title cannot be empty');
        }
        this._title = title;
    }

    defineNewTitle(newContent) {
        this.title = newContent + this.title;
    } 

    assignNewTitle() {
        $(this.selector).text(this.title);
    }
}

var modal = new Modal("#mainTitle");

modal.title = "Standards";

modal.defineNewTitle("JavaScript ");

modal.assignNewTitle();

class ChildModal extends Modal {
    constructor(selector, title) {
        super(selector, title);
    }

    defineChildTitle(title) {
        this.title = title + this.title;
    }

    assignChildTitle() {
        $(this.selector).text(this.title);
    }
}

var child = new ChildModal("#childTitle");
child.title = "JavaScript Standards"
child.defineChildTitle("Wow ");
child.assignChildTitle();
<!DOCTYPE html>
<html>
<head>
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
 <title>Class test</title>
 <h1 id="mainTitle">
  Main title
 </h1>
 <h2 id="childTitle">
  Child title
</head>
<body>
 <script src="Modal.js"></script>
</body>
</html>

Class 实例之间不共享标题、选择器和文档等字段。因此,当您为拳头 modal 变量分配标题时,它不会影响任何其他实例或 classes.

当 ChildModal 调用 super(selector, title) 时,它会将其标题参数传递给 Modal 的初始化程序。在 Modal class 中,然后将其存储在 document 字段中。

然后 运行 this.title = title + this.title; 标题字段没有任何值。是undefined。因此,标题最终为 "Wow" + undefined,结果为 "Wow undefined".

在幕后,ES5 classes 仍然使用 prototype

所以,另一个解决方案是将 modal.title = "Standards"; 更改为 Modal.prototype.title = "Standards";

这样,您不会更改实例中的 属性,但会更改原型中的值(又名 class 定义):

class Modal {
    constructor(selector, document) {
        this.selector = selector;
        this.document = document;
    }

    get title() {
        return this._title;
    }

    set title(title) {
        if(!title) {
            throw new Error('Original title cannot be empty');
        }
        this._title = title;
    }

    defineNewTitle(newContent) {
        this.title = newContent + this.title;
    } 

    assignNewTitle() {
        $(this.selector).text(this.title);
    }
}

var modal = new Modal("#mainTitle");

Modal.prototype.title = "Standards";

modal.defineNewTitle("JavaScript ");

modal.assignNewTitle();

class ChildModal extends Modal {
    constructor(selector, title) {
        super(selector, title);
    }

    defineChildTitle(title) {
        this.title = title + this.title;
    }

    assignChildTitle() {
        $(this.selector).text(this.title);
    }
}

var child = new ChildModal("#childTitle");
child.defineChildTitle("Wow ");
child.assignChildTitle();
<!DOCTYPE html>
<html>
<head>
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
 <title>Class test</title>
 <h1 id="mainTitle">
  Main title
 </h1>
 <h2 id="childTitle">
  Child title
</head>
<body>
 <script src="Modal.js"></script>
</body>
</html>