«Это строка?» — вопрос, который мучает каждого JavaScript-разработчика
Вы пишете код, и вдруг останавливаетесь. Вроде бы переменная должна содержать строку, но вдруг туда попал null? Или число? Или, что ещё хуже, undefined?
Знакомо? Если да — вы не одиноки. Вопрос «Check if a variable is a string in JavaScript» — один из самых популярных на Stack Overflow с десятками тысяч просмотров. И это не случайно: JavaScript — язык с динамической типизацией, и ошибки, связанные с типами, случаются даже у опытных разработчиков.
В этой статье мы разберём все возможные способы проверки, является ли переменная строкой. Вы узнаете:
- Почему
typeof— ваш лучший друг (но не всегда) - Когда
instanceofподводит - Как работает «снайперский» метод
Object.prototype.toString - И что делать, если вы используете библиотеки
Поехали! 🚀
Способ №1: typeof — классика жанра
Самый простой и быстрый способ — оператор typeof. Он возвращает строку с названием типа:
const name = "Алиса";
const age = 25;
const isAdmin = true;
console.log(typeof name); // "string"
console.log(typeof age); // "number"
console.log(typeof isAdmin); // "boolean"
Проверка на строку выглядит так:
if (typeof variable === "string") {
console.log("Да, это строка!");
}
Плюсы:
- Работает быстро
- Не требует импорта
- Читабельно
Минусы:
- Не отличает примитив
"строка"от объектаnew String("строка") - Для
nullвозвращает"object"(историческая ошибка JavaScript)
Кстати, про null — это известный баг языка, который уже не исправят, чтобы не сломать старые сайты. Так что typeof null === "object" — это норма.
А что с new String()?
В JavaScript есть два вида строк: примитивные (обычные) и объектные (созданные через new String()). На практике вы почти никогда не будете использовать new String(), но знать о нём стоит:
const primitiveString = "Привет";
const objectString = new String("Привет");
console.log(typeof primitiveString); // "string"
console.log(typeof objectString); // "object"
Если в вашем коде кто-то (или что-то) передаёт объектную строку, typeof вас обманет. Но не волнуйтесь: в реальных проектах такое встречается редко.
Способ №2: instanceof — для объектных строк
Оператор instanceof проверяет, является ли объект экземпляром определённого класса:
const str = new String("Тест");
console.log(str instanceof String); // true
const str2 = "Тест";
console.log(str2 instanceof String); // false — потому что это примитив
Как видите, instanceof не работает с примитивными строками. Поэтому его используют редко — только если вы точно знаете, что работаете с объектами.
Когда может пригодиться? Если вы пишете библиотеку, которая принимает и примитивы, и объекты. Но для 99% случаев typeof будет достаточно.
Способ №3: Object.prototype.toString.call() — универсальный солдат
Этот метод — настоящий снайпер. Он работает для любых типов данных и никогда не ошибается:
function isString(value) {
return Object.prototype.toString.call(value) === "[object String]";
}
console.log(isString("Привет")); // true
console.log(isString(new String("Привет"))); // true
console.log(isString(123)); // false
console.log(isString(null)); // false
console.log(isString(undefined)); // false
Как это работает? Object.prototype.toString возвращает внутренний тег типа в формате [object Type]. Для строк это всегда [object String], независимо от того, примитив это или объект.
Плюсы:
- Работает для всех типов
- Отличает примитивы от объектов
- Не даёт ложных срабатываний
Минусы:
- Длинная запись
- Чуть медленнее
typeof
Этот метод часто используют в библиотеках, где важна надёжность. Например, в jQuery, Lodash и других.
Способ №4: Lodash _.isString() — если вы не хотите думать
Если ваш проект использует Lodash (а многие используют), можно воспользоваться готовой функцией:
import _ from 'lodash';
console.log(_.isString("Привет")); // true
console.log(_.isString(new String("Привет"))); // true
console.log(_.isString(42)); // false
Под капотом Lodash использует Object.prototype.toString, так что результат будет таким же. Но код становится чище и читабельнее.
Когда использовать? Если Lodash уже есть в зависимостях — смело берите. Если нет — не стоит подключать целую библиотеку ради одной функции.
Какой способ выбрать? Сравнительная таблица
Давайте сведём всё в одну таблицу, чтобы было наглядно:
| Метод | Примитивная строка | Объектная строка | Другие типы | Скорость |
|---|---|---|---|---|
typeof |
✅ | ❌ | ✅ | 🚀 Быстро |
instanceof |
❌ | ✅ | ✅ | 🚀 Быстро |
Object.prototype.toString |
✅ | ✅ | ✅ | 🐢 Чуть медленнее |
_.isString |
✅ | ✅ | ✅ | 🐢 Зависит от Lodash |
Как видите, для повседневных задач typeof — идеальный выбор. Если вам нужно гарантированно отловить и объектные строки — используйте Object.prototype