Spec-Zone.ru › JavaScript

Symbol.unscopables

Baseline Ограниченная доступность

Эта функция не является Baseline, так как она не работает в некоторых из наиболее широко используемых браузеров.

Статическое свойство данных Symbol.unscopables представляет собой хорошо известный символ Symbol.unscopables. Оператор with ищет этот символ в объекте области видимости для свойства, содержащего коллекцию свойств, которые не должны становиться привязками в среде with.

Попробуйте

const object = {
  foo: 42,
};

object[Symbol.unscopables] = {
  foo: true,
};

with (object) {
  console.log(foo);
  // Expected output: Error: foo is not defined
}

Значение

Хорошо известный символ Symbol.unscopables.

Атрибуты свойства Symbol.unscopables
Записываемый нет
Перечисляемый нет
Конфигурируемый нет

Описание

Символ [Symbol.unscopables] (доступ к которому осуществляется через Symbol.unscopables) может быть определен в любом объекте, чтобы исключить имена свойств из отображения в качестве лексических переменных в привязках области видимости оператора with. Обратите внимание, что при использовании строгого режима операторы with недоступны, и этот символ, вероятно, не понадобится.

Присвоение свойству объекта [Symbol.unscopables] значения true (или любого истинного значения) сделает соответствующее свойство объекта области видимости with невидимым и, следовательно, оно не будет введено в область видимости тела with. Присвоение свойству значения false (или любого ложного значения) сделает его видимым и, таким образом, оно появится как переменная лексической области видимости.

При определении того, является ли x невидимым, вся цепочка прототипов свойства [Symbol.unscopables] проверяется на наличие свойства с именем x. Это означает, что если бы вы объявили [Symbol.unscopables] как простой объект, свойства Object.prototype, такие как toString, также стали бы невидимыми, что может вызвать проблемы обратной совместимости для устаревшего кода, предполагающего, что эти свойства обычно видимы (см. пример ниже). Рекомендуется, чтобы ваше пользовательское свойство [Symbol.unscopables] имело null в качестве своего прототипа, как это делает Array.prototype[Symbol.unscopables].

Этот протокол также используется API DOM, такими как Element.prototype.append().

Примеры

Область видимости в операторах with

Следующий код корректно работает в ES5 и ниже. Однако в ECMAScript 2015 был введен метод Array.prototype.values(). Это означает, что внутри среды with «values» теперь будет методом Array.prototype.values(), а не переменной вне оператора with.

var values = [];

with (values) {
  // If [Symbol.unscopables] did not exist, values would become
  // Array.prototype.values starting with ECMAScript 2015.
  // And an error would have occurred.
  values.push("something");
}

Код, содержащий with (values), вызвал сбои на некоторых веб-сайтах в Firefox при добавлении Array.prototype.values() (Firefox Bug 883914). Кроме того, это подразумевает, что любое будущее добавление метода массива может привести к ошибкам, если оно неявно изменяет область видимости with. Поэтому символ [Symbol.unscopables] был введен и реализован в Array как Array.prototype[Symbol.unscopables], чтобы предотвратить попадание некоторых методов массива в область видимости оператора with.

Невидимые объекты

Вы также можете установить [Symbol.unscopables] для своих собственных объектов.

const obj = {
  foo: 1,
  bar: 2,
  baz: 3,
};

obj[Symbol.unscopables] = {
  // Make the object have `null` prototype to prevent
  // `Object.prototype` methods from being unscopable
  __proto__: null,
  // `foo` will be scopable
  foo: false,
  // `bar` will be unscopable
  bar: true,
  // `baz` is omitted; because `undefined` is falsy, it is also scopable (default)
};

with (obj) {
  console.log(foo); // 1
  console.log(bar); // ReferenceError: bar is not defined
  console.log(baz); // 3
}

Избегайте использования объекта с не-null-прототипом в качестве [Symbol.unscopables]

Объявление [Symbol.unscopables] как простого объекта без устранения его прототипа может привести к тонким ошибкам. Рассмотрите следующий код, работавший до [Symbol.unscopables]:

const character = {
  name: "Yoda",
  toString: function () {
    return "Use with statements, you must not";
  },
};

with (character) {
  console.log(name + ' says: "' + toString() + '"'); // Yoda says: "Use with statements, you must not"
}

Для сохранения обратной совместимости вы решили добавить свойство [Symbol.unscopables] при добавлении дополнительных свойств к character. Вы можете наивно сделать это так:

const character = {
  name: "Yoda",
  toString: function () {
    return "Use with statements, you must not";
  },
  student: "Luke",
  [Symbol.unscopables]: {
    // Make `student` unscopable
    student: true,
  },
};

Однако приведенный выше код теперь нарушается:

with (character) {
  console.log(name + ' says: "' + toString() + '"'); // Yoda says: "[object Undefined]"
}

Это происходит потому, что при поиске character[Symbol.unscopables].toString возвращается Object.prototype.toString(), что является истинным значением, таким образом, вызов toString() в операторе with() ссылается на globalThis.toString() — и поскольку он вызывается без this, this равен undefined, что приводит к возврату [object Undefined].

Даже когда метод не переопределен character, делая его невидимым, это изменит значение this.

const proto = {};
const obj = { __proto__: proto };

with (proto) {
  console.log(isPrototypeOf(obj)); // true; `isPrototypeOf` is scoped and `this` is `proto`
}

proto[Symbol.unscopables] = {};

with (proto) {
  console.log(isPrototypeOf(obj)); // TypeError: Cannot convert undefined or null to object
  // `isPrototypeOf` is unscoped and `this` is undefined
}

Чтобы исправить это, всегда убедитесь, что [Symbol.unscopables] содержит только те свойства, которые вы хотите сделать невидимыми, без свойств Object.prototype.

const character = {
  name: "Yoda",
  toString: function () {
    return "Use with statements, you must not";
  },
  student: "Luke",
  [Symbol.unscopables]: {
    // Make the object have `null` prototype to prevent
    // `Object.prototype` methods from being unscopable
    __proto__: null,
    // Make `student` unscopable
    student: true,
  },
};

Спецификации

Спецификация
ECMAScript® 2027 Language Specification
# sec-symbol.unscopables

Совместимость с браузерами

Настольный компьютер Мобильный Сервер
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
unscopables
38
12
48
25
9
38
48
25
9
3.0
38
9
1.0.0
1.0
0.12.0

См. также

  • Array.prototype[Symbol.unscopables]
  • with
  • Element.prototype.append()

© 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/Global_Objects/Symbol/unscopables

Spec-Zone.ru

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