Как из объекта String получить примитив строки в JavaScript?
Что проверяют
Понимаете ли вы разницу между примитивом 'abc' и объектом-обёрткой new String('abc') и как движок превращает объект в примитив. Следом почти всегда спрашивают, почему new String('a') === 'a' даёт false и зачем обёртки вообще существуют.
Как отвечать
Сначала база: строка-примитив и объект String это разные типы. typeof 'abc' вернёт 'string', а typeof new String('abc') вернёт 'object'. Когда вы пишете 'abc'.length, движок на мгновение создаёт обёртку, берёт у неё свойство и выбрасывает, поэтому методы у примитива «есть».
Способы получить примитив:
valueOf(): прямой путь, уString.prototypeвозвращает внутреннее строковое значение объекта;toString(): у обёртки даёт тот же результат, но его можно переопределить на конкретном объекте;String(obj): вызов безnewприводит к строке любое значение, включаяnull,undefinedиSymbol;- конкатенация и шаблонная строка:
obj + ''и подстановка в шаблон запускают общий алгоритмToPrimitive.
Про ToPrimitive стоит сказать отдельно: движок сначала ищет у объекта Symbol.toPrimitive, затем при подсказке "string" начинает с toString, а при "default" и "number" с valueOf. Для обёртки String оба пути дают одну и ту же строку, но на своих классах порядок уже важен.
Практический вывод: в рабочем коде new String не пишут. Обёртка всегда истинна в условии, даже new String(''), а строгое сравнение с примитивом ломается.
Где спотыкаются
Считают, что new String('a') == new String('a') вернёт true. Это два разных объекта, сравнение идёт по ссылке, результат false. А вот == с примитивом сработает, потому что объект приведётся.
Путают String(x) и new String(x). Первое возвращает примитив, второе создаёт объект, и вся разница в одном слове.
Забывают, что у null и undefined метода toString нет вовсе: x.toString() на них упадёт с TypeError, а String(x) спокойно вернёт 'null' и 'undefined'.