Как определить, является ли переменная строкой или другим типом в JavaScript?
Самые надежные способы проверки, является ли переменная строкой в JavaScript, включают использование оператора typeof, оператора instanceof и метода Object.prototype.toString.call(). Каждый подход имеет свои преимущества и варианты использования в зависимости от ваших конкретных потребностей и среды JavaScript, в которой вы работаете.
Содержание
- Оператор typeof
- Оператор instanceof
- Метод Object.prototype.toString.call()
- Проверка конструктора String
- Сравнение методов
- Практические примеры
- Особые случаи и соображения
Оператор typeof
Оператор typeof - это самый простой метод проверки, является ли переменная строкой. Он возвращает строку, указывающую тип невыраженного операнда.
let myString = "Hello, World!";
let myNumber = 42;
let myObject = {};
let myNull = null;
let myUndefined = undefined;
console.log(typeof myString); // "string"
console.log(typeof myNumber); // "number"
console.log(typeof myObject); // "object"
console.log(typeof myNull); // "object" (это известная особенность)
console.log(typeof myUndefined); // "undefined"
Преимущества:
- Просто и быстро
- Работает с примитивными значениями и объектами
- Не нужно вызывать никаких методов
Недостатки:
typeof nullвозвращает"object"(это известная ошибка в JavaScript)- Может быть спутан с упакованными строковыми объектами
let boxedString = new String("Hello");
console.log(typeof boxedString); // "object"
Оператор instanceof
Оператор instanceof проверяет, есть ли в цепочке прототипов объекта прототип свойства конструктора. Для примитивных строк нужно использовать конструктор String.
let myString = "Hello, World!";
let myBoxedString = new String("Hello");
console.log(myString instanceof String); // false (примитив не является экземпляром String)
console.log(myBoxedString instanceof String); // true (упакованная строка является экземпляром String)
// Для примитивных строк можно использовать:
console.log(myString instanceof Object); // false (примитивы не являются объектами)
Преимущества:
- Хорошо работает с экземплярами объектов
- Может быть расширен в цепочках прототипов
Недостатки:
- Плохо работает с примитивными строками
- Может быть изменен путем изменения цепочек прототипов
- Возвращает
falseдля примитивных значений
Метод Object.prototype.toString.call()
Этот метод является самым надежным способом проверки типов, включая строки. Он возвращает строку, представляющую тип объекта.
let myString = "Hello, World!";
let myBoxedString = new String("Hello");
let myNumber = 42;
let myObject = {};
console.log(Object.prototype.toString.call(myString)); // "[object String]"
console.log(Object.prototype.toString.call(myBoxedString)); // "[object String]"
console.log(Object.prototype.toString.call(myNumber)); // "[object Number]"
console.log(Object.prototype.toString.call(myObject)); // "[object Object]"
Преимущества:
- Работает как с примитивными, так и с упакованными строками
- Последователен в различных средах JavaScript
- Не подвержен манипуляциям с прототипами
Недостатки:
- Более многословный, чем
typeof - Немного медленнее по производительности
- Возвращает строку, которую нужно проверить
function isString(value) {
return Object.prototype.toString.call(value) === '[object String]';
}
console.log(isString("Hello")); // true
console.log(isString(new String("Hi"))); // true
console.log(isString(42)); // false
Проверка конструктора String
Вы также можете проверить, является ли значение строкой, сравнивая его с конструктором String или используя функцию String().
let myString = "Hello, World!";
let myBoxedString = new String("Hello");
console.log(myString.constructor === String); // true
console.log(myBoxedString.constructor === String); // true
// Использование конструктора String
console.log(myString instanceof String); // false (примитив)
console.log(myBoxedString instanceof String); // true (упакованная)
Важное замечание: Этот метод не работает для значений null и undefined, поскольку у них нет свойства constructor.
let myNull = null;
let myUndefined = undefined;
console.log(myNull?.constructor === String); // TypeError: Cannot read properties of null
console.log(myUndefined?.constructor === String); // TypeError: Cannot read properties of undefined
Сравнение методов
Вот таблица сравнения различных методов:
| Метод | Примитивная строка | Упакованная строка | Null | Undefined | Производительность |
|---|---|---|---|---|---|
typeof |
✅ "string" |
❌ "object" |
❌ "object" |
✅ "undefined" |
Самый быстрый |
instanceof String |
❌ false |
✅ true |
❌ false |
❌ false |
Быстрый |
Object.prototype.toString.call() |
✅ "[object String]" |
✅ "[object String]" |
✅ "[object Null]" |
✅ "[object Undefined]" |
Средняя |
constructor === String |
✅ true |
✅ true |
❌ Ошибка | ❌ Ошибка | Быстрый |
Практические примеры
Базовая функция проверки типа
function isString(value) {
return typeof value === 'string';
}
console.log(isString("hello")); // true
console.log(isString(123)); // false
console.log(isString(null)); // false
console.log(isString(undefined)); // false
Комплексная функция проверки типа
function isString(value) {
// Самый надежный метод
return Object.prototype.toString.call(value) === '[object String]';
}
// Альтернатива с использованием typeof (быстрее, но менее комплексная)
function isStringFast(value) {
return typeof value === 'string';
}
// Тест с различными типами
console.log(isString("hello")); // true
console.log(isString(new String("hi"))); // true
console.log(isString(42)); // false
console.log(isString(null)); // false
console.log(isString(undefined)); // false
console.log(isString({})); // false
console.log(isString([])); // false
Безопасная обработка null и undefined
function safeIsString(value) {
if (value === null || value === undefined) {
return false;
}
return typeof value === 'string';
}
// Или с использованием опциональной цепочки
function safeIsStringModern(value) {
return typeof value?.constructor === 'function' &&
value.constructor === String;
}
Особые случаи и соображения
Строковые объекты vs примитивные строки
let primitive = "hello";
let boxed = new String("hello");
console.log(typeof primitive); // "string"
console.log(typeof boxed); // "object"
console.log(primitive === boxed); // false
Совместимость между средами
Различные среды JavaScript могут иметь разное поведение:
// Различия между Node.js и браузером
console.log(typeof document); // "object" в браузере, "undefined" в Node.js
console.log(typeof window); // "object" в браузере, "undefined" в Node.js
Соображения о производительности
Для критически важного по производительности кода, typeof - самый быстрый вариант:
// Бенчмарк различных методов
console.time('typeof');
for (let i = 0; i < 1000000; i++) {
typeof "test" === "string";
}
console.timeEnd('typeof');
console.time('toString');
for (let i = 0; i < 1000000; i++) {
Object.prototype.toString.call("test") === "[object String]";
}
console.timeEnd('toString');
Соображения безопасности
Имейте в виду, что instanceof может быть изменен:
// Злонамеренный код может изменить String.prototype
String.prototype.valueOf = function() { return {}; };
let s = "hello";
console.log(s instanceof String); // true (но опасно!)
Источники
- MDN Web Docs - оператор typeof
- MDN Web Docs - оператор instanceof
- MDN Web Docs - Object.prototype.toString()
- Спецификация языка ECMAScript - оператор typeof
- JavaScript.info - Преобразование типов
Заключение
- Оператор
typeof- это самый простой и быстрый метод проверки примитивных строк, но он не работает с упакованными строками и имеет особенность сnull Object.prototype.toString.call()- самый надежный метод, который последовательно работает как с примитивными, так и с упакованными строками, но он более многословныйinstanceof Stringработает только с упакованными строковыми объектами и возвращаетfalseдля примитивных строк- В большинстве случаев
typeof value === 'string'обеспечивает лучший баланс простоты и производительности - Учитывайте свои конкретные потребности: если вам нужно обрабатывать упакованные строки или требуется максимальная надежность, используйте
Object.prototype.toString.call(value) === '[object String]' - Всегда учитывайте среду JavaScript и потенциальные манипуляции с прототипами при выборе метода проверки типа
Выберите метод, который лучше всего соответствует вашим конкретным требованиям, учитывая производительность, надежность и типы значений, которые вам нужно обрабатывать.