Spec-Zone.ru › JavaScript

TypeError: нельзя получить доступ/установить частное поле или метод: объект имеет неверный класс

JavaScript-исключение "нельзя получить доступ/установить частное поле или метод: объект имеет неверный класс" или "нельзя установить частное поле: объект имеет неверный класс" возникает, когда частное поле или метод считывается или записывается для объекта, у которого нет этого частного элемента.

Сообщение

TypeError: Cannot read private member #x from an object whose class did not declare it (V8-based)
TypeError: Cannot write private member #x to an object whose class did not declare it (V8-based)
TypeError: can't access private field or method: object is not the right class (Firefox)
TypeError: can't set private field: object is not the right class (Firefox)
TypeError: Cannot access invalid private field (evaluating 'this.#x') (Safari)

Тип ошибки

TypeError

Что пошло не так?

Вы пытаетесь получить или установить частное поле или метод объекта, но этот объект не содержит данного частного элемента. Частные свойства экземпляра могут быть доступны только на экземплярах класса (включая его подклассы), который их объявляет; частные статические свойства могут быть доступны только на самом классе, который их объявляет, и не на подклассах.

Эта ошибка возникает, когда частное имя существует в области видимости класса, но объект, к которому осуществляется доступ, недействителен. Если частное имя не существует, вместо этого вы получите синтаксическую ошибку.

Примеры

Несоответствующие статические/экземплярные поля

Возможно, вы объявили поле как статическое, но пытаетесь получить к нему доступ через экземпляр, или наоборот.

class MyClass {
  static #x = 0;
  doSomething() {
    console.log(this.#x);
  }
}

const obj = new MyClass();
obj.doSomething();
// TypeError: can't access private field: object is not the right class

Чтобы исправить это, либо измените поле на поле экземпляра, либо получите доступ к полю через сам класс, либо объявите другое поле в экземпляре. Обратите внимание, что частное пространство имен совместно используется между статическими и экземплярными свойствами, поэтому вы не можете иметь статический и экземплярный частный элемент с одинаковым именем.

class MyClass {
  #x = 0;
  doSomething() {
    console.log(this.#x);
  }
}

class MyClass2 {
  static #x = 0;
  doSomething() {
    console.log(MyClass2.#x);
  }
}

Использован неправильный объект

Возможно, у вас есть метод, который обращается к this.#x, но он вызывается с другим значением this.

class JSONReplacer {
  #count = 0;
  func(key, value) {
    if (typeof value === "object") {
      this.#count++;
    }
    return value;
  }
}

JSON.stringify({ a: 1, b: { c: 2 } }, new JSONReplacer().func);
// TypeError: can't access private field: object is not the right class

Это связано с тем, что JSON.stringify() вызывает функцию-заменитель с объектом, содержащим value, в качестве this, поэтому частное поле недоступно. Чтобы исправить это, вы можете привязать метод к объекту или использовать стрелочную функцию, чтобы гарантировать, что replacer.func будет вызван с правильным значением this.

const replacer = new JSONReplacer();
JSON.stringify({ a: 1, b: { c: 2 } }, replacer.func.bind(replacer));
JSON.stringify({ a: 1, b: { c: 2 } }, (...args) => replacer.func(...args));

В большинстве случаев, если вы случайно отвязали метод, метод будет вызван с undefined в качестве this, что приведет к другой ошибке (TypeError: нельзя преобразовать undefined в object). Эта ошибка возникает только тогда, когда метод вызывается с другим объектом в качестве this, либо с помощью call(), либо apply(), либо путем передачи метода в качестве обратного вызова функции, которая вызывает его с другим значением this.

Если вы не уверены, что объект будет содержать частный элемент, как в следующем коде:

class MyClass {
  #x = 0;
  static doSomething(obj) {
    console.log(obj.#x); // Throws if obj is not an instance of MyClass
  }
}

Вы можете использовать оператор in для выполнения брендированной проверки.

class MyClass {
  #x = 0;
  static doSomething(obj) {
    if (!(#x in obj)) {
      return;
    }
    console.log(obj.#x);
  }
}

Доступ к статическим элементам в подклассах

Если у вас есть статическое частное свойство, вы можете получить к нему доступ только в классе, который его объявляет, а не в подклассах.

class MyClass {
  static #x = 0;
  doSomething() {
    console.log(this.#x);
  }
}

class MySubClass extends MyClass {}

MySubClass.doSomething();
// TypeError: can't access private field: object is not the right class

Чтобы исправить это, никогда не обращайтесь к частным статическим свойствам через this. Вместо этого всегда явно указывайте имя класса.

class MyClass {
  static #x = 0;
  doSomething() {
    console.log(MyClass.#x);
  }
}

Доступ к частным элементам с одинаковым именем в другом классе

В отличие от обычных строковых или символьных свойств, частные имена не совместно используются между классами. Если у вас есть частный элемент с одинаковым именем в двух классах, они все равно не являются одним и тем же элементом, и вы не можете получить доступ к частному элементу одного класса из другого класса.

class MyClass {
  #x = 0;
}

class MyOtherClass {
  #x = 1;
  doSomething(o) {
    console.log(o.#x);
  }
}

const obj = new MyClass();
new MyOtherClass().doSomething(obj);
// TypeError: can't access private field: object is not the right class

Добавление частных элементов к несвязанным объектам

Вы не можете динамически добавлять частные элементы к несвязанным объектам.

class MyClass {
  #x = 0;
  static stamp(obj) {
    obj.#x = 1;
  }
}

MyClass.stamp({});
// TypeError: can't set private field: object is not the right class

Если вы действительно хотите это сделать, рассмотрите возможность использования приема return override. Однако, в целом, вы, вероятно, захотите использовать WeakMap вместо этого.

class MyClass {
  static #objToX = new WeakMap();
  static stamp(obj) {
    MyClass.#objToX.set(obj, 1);
  }
}

MyClass.stamp({});

См. также

  • Классы
  • Частные элементы

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Get_set_missing_private

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API