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,
},
};
Спецификации
Совместимость с браузерами
| Настольный компьютер | Мобильный | Сервер | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 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 |
См. также
© 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