Тот самый канал по JavaScript.
Личный блог автора - @just_genych
По вопросам рекламы или разработки: @g_abashkin
Post #3606
318
Symbol.toStringTag — тот самый символ, который ломает всё подряд
Казалось бы, просто добавил
Сериализация и JSON
Прямого влияния на
* Типичная ошибка: проверять тип через тег, а не через
* Практический совет: в кастомной сериализации используй отдельное поле
Прототипы под прицелом
Многие фреймворки определяют тип через
* Предупреждение: не трогай
* Trade-off: изменяя тег на прототипе встроенных типов, ты создаёшь скрытые зависимости от строковых сравнений в чужих модулях.
shouldOverrideVisibility и production-фреймворки
В недрах React Native или Vue 2 composition API есть функция, которая проверяет видимость компонента через
Пример бага:
* Чтобы защититься в HOC: прокидывай тег через
Вывод: Маленький символ
Казалось бы, просто добавил
[Symbol.toStringTag] в класс, получил [object MyCoolClass] — и радуешься. Но production показывает, что это "удобство" превращает дебаг в квест: особенно когда фреймворк или библиотека ожидают строгий "Object", "Array" или "Promise", а получают что-то своё.Сериализация и JSON
Прямого влияния на
JSON.stringify() нет. Но если пишешь свой toJSON(), где проверяешь this[Symbol.toStringTag] — вот тут баг. Класс-наследник с другим тегом превращается в родительский тип. Я такое ловил, когда сериализовал DTO: потомок считался предком, и бэкенд падал с валидацией.* Типичная ошибка: проверять тип через тег, а не через
this.constructor.name.* Практический совет: в кастомной сериализации используй отдельное поле
_typeTag.Прототипы под прицелом
Многие фреймворки определяют тип через
Object.prototype.toString.call(obj). Зачем? Потому что typeof не отличает Array от обычного объекта. А если ты переопределил тег в прототипе (например, сделал Array.prototype[Symbol.toStringTag] = "MyArray") — библиотека, ожидающая "Array", просто сломает иммутабельность или реактивность. Видел такое в старых полифиллах.* Предупреждение: не трогай
Symbol.toStringTag в прототипах Array, Promise, Map — движок использует их для внутренних проверок.* Trade-off: изменяя тег на прототипе встроенных типов, ты создаёшь скрытые зависимости от строковых сравнений в чужих модулях.
shouldOverrideVisibility и production-фреймворки
В недрах React Native или Vue 2 composition API есть функция, которая проверяет видимость компонента через
Symbol.toStringTag. Кейс: обернул компонент в HOC, HOC перетирает тег. shouldOverrideVisibility сравнивает тег с ожидаемым — и игнорирует компонент как "чужой". Элементы рендерятся, но никогда не становятся видимыми. Это не баг документации — это примитивная проверка на уровне типа.Пример бага:
class Base {
get [Symbol.toStringTag]() { return "Base" }
}
class Child extends Base {}
// Child будет сериализоваться как Base* Чтобы защититься в HOC: прокидывай тег через
Object.defineProperty с оригинальным значением.Вывод: Маленький символ
Symbol.toStringTag — это скрытая точка отказа при сериализации, защите прототипов и в production-фреймворках, поэтому относись к нему как к мине — лучше не трогать, если не контролируешь все уровни стека.


