JavaScript: я не могу создать экземпляр класса - PullRequest
1 голос
/ 26 апреля 2020

Я пытаюсь создать объектно-ориентированное приложение, но я не могу ссылаться или создавать экземпляры каких-либо созданных мной классов. Я следовал синтаксису, взятому из 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>

1 Ответ

3 голосов
/ 26 апреля 2020

Проблема в том, что в Hero вы определили name как свойство доступа, но в методах доступа вы рассматриваете name, как будто это свойство данных, которое вызывает бесконечное l oop. Если вы заглянете в devtools вашего браузера, вы увидите исключение переполнения стека.

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;
// −−−−−−−−−−^
    }
}

Live Пример:

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;
    }
}

Live Example :

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 . (Вы можете использовать это уже, если переносите через Babel.) Вот пример, который работает в некоторых современных браузерах (включая последние Chrome, Chromium, Brave и Chromium-based 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>
...