JavaScript:我无法实例化一个类



我正在尝试创建一个面向对象的应用程序,但我无法引用或实例化我创建的任何类。我一直遵循的语法取自https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes和其他来源,但似乎什么都不起作用(我使用的是在线沙盒(。

在下面的代码中,永远不会到达第二个alert语句。有人知道为什么吗?Fiddle:https://jsfiddle.net/chokpjsd/16/#&togetherjs=jKAgOFu0og

JavaScript

class Hero {
constructor(heroName) {
this.name = heroName;
}
get name() {
return this.name;
}
set name(newName) {
this.name = newName;
}
}
function getHeros() {
alert("hi");
var hero1 = new Hero("Superman");
alert("hi 2");
alert(hero1.name);
document.getElementById("HerosContainer").innerHTML = "<p>" + hero1.name + "</p>";
}
<body>
<h1>
Hello World!
</h1>
<button onclick="getHeros()">
Get Heros
</button>
<div id="HerosContainer">
</div>
</body>

问题是,在Hero中,您已将name定义为访问器属性,但在访问器方法中,您将name视为数据属性,这会导致无限循环。如果你查看浏览器的开发工具,你会看到一个堆栈溢出异常。

class Hero {
constructor(heroName) {
this.name = heroName;
}
get name() {
return this.name; // <=== Calls `get name` again, then again, then again...
}
set name(newName) {
this.name = newName;  // <=== Calls `set name` again, then again, then again...
}
}

如果要将name定义为访问器属性,则必须将其值存储在其他位置。一个流行的选择是另一个前缀为下划线的属性,表示"在Hero类之外的代码中不要使用此属性":

class Hero {
constructor(heroName) {
this._name = heroName;
// −−−−−−−−−−^
}
get name() {
return this._name;
// −−−−−−−−−−−−−−−−−^
}
set name(newName) {
this._name = newName;
// −−−−−−−−−−^
}
}

实例:

class Hero {
constructor(heroName) {
this._name = heroName;
}
get name() {
return this._name;
}
set name(newName) {
this._name = newName;
}
}
function getHeros() {
console.log("hi");
var hero1 = new Hero("Superman");
console.log("hi 2");
console.log(hero1.name);
document.getElementById("HerosContainer").innerHTML = "<p>" + hero1.name + "</p>";
}
<h1>
Hello World!
</h1>
<button onclick="getHeros()">
Get Heros
</button>
<div id="HerosContainer">
</div>

但是,如果您不需要它作为访问器属性,只需完全删除访问器方法即可:

class Hero {
constructor(heroName) {
this.name = heroName;
}
}

实例:

class Hero {
constructor(heroName) {
this.name = heroName;
}
}
function getHeros() {
console.log("hi");
var hero1 = new Hero("Superman");
console.log("hi 2");
console.log(hero1.name);
document.getElementById("HerosContainer").innerHTML = "<p>" + hero1.name + "</p>";
}
<h1>
Hello World!
</h1>
<button onclick="getHeros()">
Get Heros
</button>
<div id="HerosContainer">
</div>


暂时回到访问器:如果您有理由将name作为访问器属性,那么很快您就可以通过新的私有字段语法将其保存在实例上的一个真正的私有字段中。(如果你通过Babel进行转换,你就可以使用它了。(下面是一个适用于一些现代浏览器的例子(包括最新的Chrome、Chromium、Brave和基于Chromium的Edge(:

class Hero {
#name; // <== Declares the field (required for private fields)
constructor(heroName) {
this.#name = heroName;
// −−−−−−−−−−^
}
get name() {
return this.#name;
// −−−−−−−−−−−−−−−−−^
}
set name(newName) {
this.#name = newName;
// −−−−−−−−−−^
}
}

实例:

class Hero {
#name;
constructor(heroName) {
this.#name = heroName;
}
get name() {
return this.#name;
}
set name(newName) {
this.#name = newName;
}
}
function getHeros() {
console.log("hi");
var hero1 = new Hero("Superman");
console.log("hi 2");
console.log(hero1.name);
document.getElementById("HerosContainer").innerHTML = "<p>" + hero1.name + "</p>";
}
<h1>
Hello World!
</h1>
<button onclick="getHeros()">
Get Heros
</button>
<div id="HerosContainer">
</div>