【问题标题】:JavaScript: I can't instantiate a classJavaScript:我无法实例化一个类
【发布时间】:2020-08-10 00:09:55
【问题描述】:

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

在下面的代码中,永远不会到达第二个警报语句。有谁知道为什么? 小提琴: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>

【问题讨论】:

    标签: javascript object scope


    【解决方案1】:

    问题在于,在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 设为访问器属性,很快您就可以通过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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-31
      • 2019-01-25
      • 2017-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      相关资源
      最近更新 更多