为什么 `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.title
? childModal
class中的思想,this.title
应该是'JavaScriptStandardas I've inherited the
Modalclass 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();
您目前正在加入 string
和 undefined
,结果是 undefined
。
由于您正在创建两个实例,它们彼此不相关,因此 child.title
与 modal.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>
我是 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.title
? childModal
class中的思想,this.title
应该是'JavaScriptStandardas I've inherited the
Modalclass 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();
您目前正在加入 string
和 undefined
,结果是 undefined
。
由于您正在创建两个实例,它们彼此不相关,因此 child.title
与 modal.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>