JavaScript: 我无法实例化 class

JavaScript: I can't instantiate a class

我正在尝试创建一个面向对象的应用程序,但我无法引用或实例化我创建的任何 类。我一直在遵循从 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes 和其他来源获取的语法,但似乎没有任何效果(我正在使用在线沙箱)。

在下面的代码中,永远不会到达第二个警报语句。有人知道为什么吗? 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 定义为访问器 属性,则必须将其值存储在别处。一个流行的选择是另一种 属性,前缀为下划线 "leave this alone in code outside the Hero class":

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 设为访问器 属性,很快您就可以通过以下方式将其保存在实例的真正私有字段中new private fields syntax。 (如果你通过 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>