为什么`super`关键字属性在ES6类中返回未定义?

时间:2019-06-05 15:18:27

标签: javascript class es6-modules

我是ES6类的新手,试图了解继承在ES6中的工作原理。我创建了一个父类Modal和一个子类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类中,this.title应该是'JavaScript Standard as I've inherited the Modal class in the constructor?此处输入代码`

3 个答案:

答案 0 :(得分:2)

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

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

当您随后运行this.title = title + this.title;时,标题字段没有任何值。是undefined。因此,标题最终以"Wow" + undefined结尾,结果为“ Wow undefined”。

答案 1 :(得分:1)

您需要在构造函数中定义_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>

答案 2 :(得分:0)

内幕之下,ES5类仍使用prototype

因此,另一种解决方案是将modal.title = "Standards";更改为Modal.prototype.title = "Standards";

通过这种方式,您将不会更改实例中的属性,但会更改原型中的值(也称为类定义):

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>