Проверьте, является ли переменная строкой в ​​JavaScript

1745

Как я могу определить, является ли переменная строкой или чем-то еще в JavaScript?

Olical
источник

Ответы:

1693

Вы можете использовать typeofоператор:

var booleanValue = true; 
var numericalValue = 354;
var stringValue = "This is a String";
var stringObject = new String( "This is a String Object" );
alert(typeof booleanValue) // displays "boolean"
alert(typeof numericalValue) // displays "number"
alert(typeof stringValue) // displays "string"
alert(typeof stringObject) // displays "object"

Пример с этой веб-страницы . (Пример был немного изменен, хотя).

Это не будет работать, как ожидается, в случае строк, созданных с помощью new String(), но это редко используется и рекомендуется против [1] [2] . Посмотрите другие ответы о том, как справиться с этим, если вы этого хотите.


  1. В Руководстве по стилю Google JavaScript говорится, что никогда не используйте примитивные обертки объектов .
  2. Дуглас Крокфорд рекомендовал, чтобы примитивные объектные обертки были устаревшими .
Пабло Санта Круз
источник
45
@ Wolfy87 Обратите внимание, что в некоторых случаях typeof stringValue может возвращать «объект» вместо «строка». Смотрите комментарии к моему ответу.
DRAX
163
Мой предпочтительный ответ. Аргумент против этого состоит в том, что он «терпит неудачу» для строк, обернутых в объект, например new String('foo'), но это не имеет значения, потому что строки, обернутые в объект, являются бесполезной функцией, которую вы не должны использовать. Руководство по стилю Google запрещает их , Дуглас Крокфорд хочет, чтобы они устарели , а библиотеки их не используют. Притворяться, что они не существуют, и использовать typeofбез страха.
Марк Амери
2
@DanielLe, потому что он предложил замену, которая исправляет некоторые проблемы, а не потому, что он против этого в принципе.
Всеволод Голованов
4
Если это вызывает у вас головную боль, то в 99,99% случаев это происходит из-за того, что вы неправильно структурировали свой код. Это не вина NaN за то, что он существует и делает то, что он делает, это то, что вы должны принять к сведению, извлечь уроки и иметь в виду, когда в следующий раз будете работать с кодом, который может дать его.
Майк 'Pomax' Камерманс
1912

Это то, что работает для меня:

if (typeof myVar === 'string' || myVar instanceof String)
// it's a string
else
// it's something else
Драка
источник
77
Делает ли myVar instanceof String что-то помимо «typeof myVar == 'string'"?
svth
81
@ я вспомнил. В JavaScript вы можете иметь переменный тип string или тип объекта, который является классом String (то же самое - оба являются строками - но определены по-разному), поэтому проверяется дважды.
DRAX
38
var somevar = new String ('somestring') console.log (typeof somevar) // объект
дунайский моряк
82
-1 потому что instanceofпроверка здесь - бессмысленный шум, если вы не следуете некоторым очень необычным методам кодирования, и этот ответ не объясняет, что он делает или почему вы можете его использовать. Единственная причина, по которой вам когда-либо это понадобится, это если вы используете строки, обернутые объектами, но строки, обернутые объектами, - бесполезная функция, которую никто не использует, и Google и Крокфорд оба осуждают как плохую практику ( google-styleguide.googlecode.com/svn/ trunk /… , crockford.com/javascript/recommend.html ).
Марк Амери
79
Я категорически не согласен с тем, что следует избегать написания твердого кода, который правильно обрабатывает маловероятные случаи. Проверка как typeofи instanceofчувствует , как хороший совет , если ваш код может быть вызван другими. Крайний postmessageслучай @ MarkAmery имеет значение, если вы спрашиваете: «Что я только что сделал postmessage?» - но вы ожидаете, что это будет обработано на интерфейсе и не разрешено распространяться. В других местах кажется правильным работать с не осуждаемыми методами кодирования, даже если некоторые эстетики JS их не одобряют. НИКОГДА не комментируйте ваш код как принимающий String, если это не так!
Деви Морган
157

Поскольку более 580 человек проголосовали за неправильный ответ, а 800+ проголосовали за рабочий, но в стиле дробовика, я подумал, что, возможно, стоит повторить мой ответ в более простой форме, понятной каждому.

function isString(x) {
  return Object.prototype.toString.call(x) === "[object String]"
}

Или встроенный (у меня есть настройка UltiSnip для этого):

Object.prototype.toString.call(myVar) === "[object String]"

К вашему сведению, ответ Пабло Санта-Круса неверен, потому что typeof new String("string") этоobject

Ответ DRAX точный и функциональный, и должен быть правильным (поскольку Пабло Санта-Крус, безусловно, неверен, и я не буду спорить с голосами избирателей).

Тем не менее, этот ответ также определенно правильный и фактически лучший ответ (за исключением, возможно, предложения использовать lodash / underscore ). Отказ от ответственности: я внес вклад в кодовую базу lodash 4.

Мой оригинальный ответ (который явно пролетел над многими головами) следующий:

Я перекодировал это из underscore.js:

['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'].forEach( 
    function(name) { 
        window['is' + name] = function(obj) {
              return toString.call(obj) == '[object ' + name + ']';
    }; 
});

Это определит isString, isNumber и т. Д.


В Node.js это может быть реализовано как модуль:

module.exports = [
  'Arguments',
  'Function', 
  'String', 
  'Number', 
  'Date', 
  'RegExp'
].reduce( (obj, name) => {
  obj[ 'is' + name ] = x => toString.call(x) == '[object ' + name + ']';
  return obj;
}, {});

[edit]: Object.prototype.toString.call(x)работает для разграничения функций и асинхронных функций:

const fn1 = () => new Promise((resolve, reject) => setTimeout(() => resolve({}), 1000))
const fn2 = async () => ({})

console.log('fn1', Object.prototype.toString.call(fn1))
console.log('fn2', Object.prototype.toString.call(fn2))

Orwellophile
источник
11
Вы рекомендуете underscore.js (по какой странной причине?), Но вы не используете его здесь. Более того, вы загрязняете глобальное пространство имен функциями. В node.js вы создадите модуль, который будет иметь все эти функции (вы можете использовать global || windowвместо него, windowно это будет плохой подход для решения проблемы, которую вы не должны иметь в первую очередь).
Бенджамин Грюнбаум
19
@BenjaminGruenbaum Я искал ответ на вопрос ОП, и мне не понравился ни один из ответов. Поэтому я проверил, что сделал подчеркивание, и подумал, что это было достаточно изящно, чтобы немного извлечь и изменить (чтобы избежать загрузки библиотеки подчеркиваний). Я уточню свой пост.
Орвеллофил
2
@ Orwellophile Круто, теперь я понял, ваш оригинальный ответ был сформулирован так, как будто вы предлагаете подчеркнуть себя. Лично я бы просто проверил, myObject+"" === myObjectчтобы проверить, является ли объект строкой (или, что еще лучше, я бы не стал проверять тип в первую очередь в управляемой поведением системе типов).
Бенджамин Грюнбаум
18
@ Orwellophile, как это лучше, чем ответ DRAX?
Pacerier
3
JS поддерживает исправление обезьян, поэтому можно переопределить toStringв Object.prototype. Итак, я бы сказал, что полагаться на toStringпроверку типа объекта - это, в лучшем случае, плохая практика.
Андре Родригес
84

Я рекомендую использовать встроенные функции из jQuery или lodash / Underscore . Они проще в использовании и легче для чтения.

Любая функция будет обрабатывать случай, упомянутый DRAX ... то есть они оба проверяют, является ли (A) переменная строковым литералом или (B) это экземпляр объекта String. В любом случае эти функции правильно идентифицируют значение как строку.

lodash / Underscore.js

if(_.isString(myVar))
   //it's a string
else
   //it's something else

JQuery

if($.type(myVar) === "string")
   //it's a string
else
   //it's something else

Видеть документацию lodash для _.isString () для более подробной информации.

См. Документацию jQuery для $ .type () для более подробной информации.

ClearCloud8
источник
97
Это самое важное, что не так с сообществом JS - проверка на примитивный тип является однострочной и включает только языковую конструкцию (одну из основных), но вы рекомендуете использовать внешнюю библиотеку. Если кто-то уже использует одну из этих библиотек, это может быть хорошей идеей, но загрузка их только для этого вместо простой проверки типа является излишним.
Rafał Wrzeszcz
5
Я собираюсь согласиться с Рафалом. Я вижу везде, что это улучшает "читаемость", чтобы использовать одну из этих внешних библиотек. Если вы знаете JavaScript, то его легче читать, чем какую-то внешнюю библиотеку, которую вы не использовали. _.every()поначалу это немного сбивает с толку, и что-то столь же простое, как _.isBoolean()запутало разработчиков в моей компании. Разработчик ошибочно полагал, что будет ложным, если значение будет логическим и будет ложным. Английский для меня легче читать, чем немецкий, потому что я не знаю немецкий. Изучайте JavaScript, и все это будет иметь смысл.
Джон Хардинг,
20
@ RafałWrzeszcz Эти библиотеки довольно широко используются и предоставляют много полезных (и проверенных) функциональных возможностей. Особенно лодаш. Я бы не рекомендовал кому-то загружать библиотеку только для использования в этом решении ... но я бы порекомендовал каждому разработчику javascript загрузить эту библиотеку и посмотреть, что им не хватает. ;)
ClearCloud8
13
Все вы упускаете смысл библиотеки вроде Lodash: не скорость. Не «простота разработки». Причиной использования такой библиотеки, как Lodash, является «защита» от проблем, которые могут взорвать ваше js-приложение. Неустранимые ошибки возникают, когда вы пытаетесь выполнить строковые операции над объектом (или наоборот), и Lodash предоставляет огромную ценность для предотвращения этих ошибок.
random_user_name
1
Имейте в виду, что многие люди будут делать это в среде Node или Node-like, и очень немногие люди будут использовать jQuery там.
Мэтт Флетчер
35
function isString (obj) {
  return (Object.prototype.toString.call(obj) === '[object String]');
}

Я видел это здесь:

http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/

вереск
источник
4
Я думаю, что это решение является наиболее надежным, поскольку оно обрабатывает перекрестные ссылочные сценарии / кросс-окна, как указано в URL-адресе, указанном в ответе.
2015 г.
1
Отличный ответ, похоже, Underscore.js также использует этот метод!
Даан
1
@ling Просто любопытно, почему вы ставите круглые скобки Object.prototype.toString.call(obj) === '[object String]'?
StubbornShowaGuy
@ Earlee Вы имеете в виду, (x === y)имеет лучшую читаемость, чем x === y?
StubbornShowaGuy
@StubbornShowaGuy По-моему, да. Это также о последовательности. Я лично всегда использую скобки при возврате значения.
Акварель
28

Лучший способ:

var s = 'String';
var a = [1,2,3];
var o = {key: 'val'};

(s.constructor === String) && console.log('its a string');
(a.constructor === Array) && console.log('its an array');
(o.constructor === Object) && console.log('its an object');
(o.constructor === Number || s.constructor === Boolean) && console.log('this won\'t run');

Каждый из них был создан соответствующей функцией класса, такой как «new Object ()» и т. Д.

Кроме того, Duck-Typing: «Если он выглядит как утка, ходит как утка и пахнет как утка - это должен быть массив». Проверьте значения.

Надеюсь это поможет.

Редактировать; 12/05/2016

Помните, что вы всегда можете использовать комбинации подходов. Вот пример использования встроенной карты действий с typeof :

var type = { 'number': Math.sqrt.bind(Math), ... }[ typeof datum ];

Вот более реальный пример использования встроенных карт:

function is(datum) {
    var isnt = !{ null: true, undefined: true, '': true, false: false, 0: false }[ datum ];
    return !isnt;
}
console.log( is(0), is(false), is(undefined), ... );  // >> true true false

Эта функция будет использовать [custom] «приведение типов», а точнее «type - / - value-mapping», чтобы выяснить, существует ли переменная на самом деле. Теперь вы можете разделить эти неприятные волосы между null&0 !

Много раз вы даже не заботитесь о его типе . Еще один способ обойти типизацию - это комбинирование наборов Duck-Type:

this.id = "998";  // use a number or a string-equivalent
function get(id) {
    if (!id || !id.toString) return;
    if (id.toString() === this.id.toString()) http( id || +this.id );
    // if (+id === +this.id) ...;
}

Оба Number.prototype и String.prototype есть .toString() method. Вы просто удостоверились, что строковый эквивалент числа был тем же самым, и затем вы убедились, что передали его в httpфункцию как Number. Другими словами, мы даже не заботились какой у него был тип.

Надеюсь, это даст вам больше возможностей для работы :)

Cody
источник
Вам понадобится другая проверка для простых старых чисел, поскольку попытка получить их свойство конструктора завершится неудачей:
@torazaburo У меня нормально работало только сейчас в консоли Chrome. Что заставляет вас думать, что это не сработает?
Марк Амери
2
@torazaburo Вы можете поиграть с утверждениями ( (o.constructor === Number || s.constructor === Boolean)). Анекдотично, parseIntи NaNхрупкие, но мощные инструменты. Просто помните, что Not-a-Number - это НЕ Not-a-Number, и можно определить undefined.
Коди
1
a.constructor === Массив неправильный и иногда может давать сбой, используйте Array.isArray, см. web.mit.edu/jwalden/www/isArray.html
axkibe
1
Согласен, это не отказоустойчиво. Лучше всего использовать проверку свойств - это единственный действительно надежный способ на данный момент. Пример: if(thing.call) { 'its a function'; }или if(thing.defineProperties) { 'its an object'; }. Спасибо за вклад, axkibe!
Коди
17

Я не могу честно понять, почему нельзя просто использовать typeofв этом случае:

if (typeof str === 'string') {
  return 42;
}

Да, он потерпит неудачу в отношении строк, обернутых объектами (например new String('foo')), но они широко расцениваются как плохая практика, и большинство современных инструментов разработки, вероятно, будут препятствовать их использованию. (Если вы видите один, просто исправьте это!)

Object.prototype.toStringХитрость заключается в то , что все интерфейсные разработчики были признаны виновными делать один день в своей карьере , но не позволяйте ему обмануть вас своей полировки умный: он сломается , как только что - то обезьяна-патч прототипа объекта:

const isString = thing => Object.prototype.toString.call(thing) === '[object String]';

console.log(isString('foo'));

Object.prototype.toString = () => 42;

console.log(isString('foo'));

customcommander
источник
15

Мне нравится использовать это простое решение:

var myString = "test";
if(myString.constructor === String)
{
     //It's a string
}
ScottyG
источник
3
Чем это отличается от ответа Коди 4 года спустя?
Джонатан Х
3
@Sheljohn Коди ответ велик. Мой ответ (полный текст) короче и прямо к делу. Вы спросили ... :)
ScottyG
Как функция, для этого потребуется способ работы с undefinedи null, и все же получение правильного ответа для пустых строк (как ''и new String('')).
MikeBeaton
@MikeBeaton Нет проблем (mystring || false) && mystring.constructor === String. Я использовал false в случае, если он используется в функции, которая должна возвращать логическое значение.
Аланс
13

Это отличный пример того, почему производительность имеет значение:

Выполнение чего-либо столь же простого, как тест на строку, может быть дорогостоящим, если не выполнено правильно.

Например, если бы я хотел написать функцию для проверки, является ли что-то строкой, я мог бы сделать это одним из двух способов:

1) const isString = str => (Object.prototype.toString.call(str) === '[object String]');

2) const isString = str => ((typeof str === 'string') || (str instanceof String));

Оба они довольно просты, так что может повлиять на производительность? Вообще говоря, вызовы функций могут быть дорогими, особенно если вы не знаете, что происходит внутри. В первом примере есть вызов функции для метода toString объекта. Во втором примере нет вызовов функций, так как typeof и instanceof являются операторами. Операторы значительно быстрее, чем вызовы функций.

Когда тестируется производительность, пример 1 на 79% медленнее, чем пример 2!

Смотрите тесты: https://jsperf.com/isstringtype

Роб Брандер
источник
Тестовая ссылка мертва, но я тебе верю. Такая информация очень важна. ИМХО, это должен быть, если не самый одобренный ответ, по крайней мере наиболее одобренный комментарий к текущему ведущему ответу.
Coderer
typeof str === 'string' || str instanceof String(могу опустить скобки, которые я предпочитаю в if (..)случаях); независимо от того, проверка как примитивных, так и объектных типов в # 2 ясна и достаточна. Эти проверки должны быть «редкими» в любом случае.
user2864740
13
if (s && typeof s.valueOf() === "string") {
  // s is a string
}

Работает как для строковых литералов, так let s = 'blah'и для объектных строкlet s = new String('blah')

wheelmaker
источник
3
Внимание! Это потерпит неудачу на пустых строках, так как они ложные.
Филипп Суми
8

Взято из Лодаш:

function isString(val) {
   return typeof val === 'string' || ((!!val && typeof val === 'object') && Object.prototype.toString.call(val) === '[object String]');
}

console.log(isString('hello world!')); // true
console.log(isString(new String('hello world'))); // true
Бендж Сикам
источник
Если кто-то хочет узнать источник, это github.com/lodash/lodash/blob/master/isString.js
Рикардо
5

Я думаю, что решения @customcommander должно хватить в 90% случаев:

typeof str === 'string'

Должен служить вам правильно (просто так как обычно нет причин иметь new String('something') в вашем коде ).

Если вы заинтересованы в обработке String объекта (например, вы ожидаете некоторого var от стороннего производителя), то использование lodash, как предложено @ ClearCloud8, кажется ясным, простым и элегантным решением.

Однако я бы посоветовал быть осторожным с такими библиотеками, как lodash, из-за их размера. Вместо того чтобы делать

import _ from 'lodash'
...
_.isString(myVar)

Который приносит весь огромный объект lodash, я бы предложил что-то вроде:

import { isString as _isString } from 'lodash'
...
_isString(myVar)

И с простой связкой у вас все должно быть в порядке (я ссылаюсь здесь на код клиента).

Эрез Коэн
источник
почему === когда == достаточно
Завр
4

Я также обнаружил, что это тоже хорошо работает и намного короче, чем другие примеры.

if (myVar === myVar + '') {
   //its string
} else {
   //its something else
}

Конкатенация в пустых кавычках превращает значение в строку. Если myVarэто уже строка, то оператор if успешен.

Крис Дельфин
источник
3
Единственная проблема в том, что вы вызываете переменную, когда хотите проверить ее тип. Это кажется немного дорогим для меня по сравнению с typeof.
Olical
1
Так что да, ты прав. jsperf сказал, что это было примерно на 20% медленнее, typeofно все же немного быстрее, чем toString. В любом случае, я думаю, мне просто нравится синтаксис для принуждения.
Крис Дельфин
4
это не работает с типом String; var s = new String('abc'); > s === s + '' > false
user5672998
1
Не работает с new Stringcus, который создает тип object. w3schools.com/js/tryit.asp?filename=tryjs_string_object2
Крис Дельфин,
Хорошая мысль, но исключает крайний случай обернутых строк.
Энтони Ратледж
4

Если вы работаете в среде node.js, вы можете просто использовать встроенную функцию isString в утилитах.

const util = require('util');
if (util.isString(myVar)) {}

Редактировать: как уже упоминалось @Jehy, это устарело начиная с v4.

Дэвид
источник
Есть ли замена?
Энтони Конг
3
В документах написано «Используйте typeof value === 'string'вместо».
мистер Роджерс
x = new String('x'); x.isString(x);возвращает ложь . Существует, util.types.isStringObject()но это возвращает ложь для x = 'x'типа строки. Две служебные функции, которые не предоставляют никакой полезности ...
spinkus
4

Следующий метод проверяет, является ли какая-либо переменная строкой ( включая переменные, которые не существуют ).

const is_string = value => {
  try {
    return typeof value() === 'string';
  } catch (error) {
    return false;
  }
};

let example = 'Hello, world!';

console.log(is_string(() => example)); // true
console.log(is_string(() => variable_doesnt_exist)); // false
Грант Миллер
источник
3
var a = new String('')
var b = ''
var c = []

function isString(x) {
  return x !== null && x !== undefined && x.constructor === String
}

console.log(isString(a))
console.log(isString(b))
console.log(isString(c))
Джейк
источник
Зачем вам нужно проверять наличие нуля или неопределенности, если x.constructor === String также возвращает false для нуля или неопределенности?
Жюль Мэнсон
1
@JulesManson: Это выдает ошибку, а не производит false.
Ry-
3

Я считаю эту простую технику полезной для проверки типов для String -

String(x) === x // true, if x is a string
                // false in every other case

const test = x =>
  console.assert
    ( String(x) === x
    , `not a string: ${x}`
    )

test("some string")
test(123)           // assertion failed
test(0)             // assertion failed
test(/some regex/)  // assertion failed
test([ 5, 6 ])      // assertion failed
test({ a: 1 })      // assertion failed
test(x => x + 1)    // assertion failed

Та же техника работает и для номера -

Number(x) === x // true, if x is a number
                // false in every other case

const test = x =>
  console.assert
    ( Number(x) === x
    , `not a number: ${x}`
    )

test("some string") // assertion failed
test(123)           
test(0)             
test(/some regex/)  // assertion failed
test([ 5, 6 ])      // assertion failed
test({ a: 1 })      // assertion failed
test(x => x + 1)    // assertion failed

А для RegExp -

RegExp(x) === x // true, if x is a regexp
                // false in every other case

const test = x =>
  console.assert
    ( RegExp(x) === x
    , `not a regexp: ${x}`
    )

test("some string") // assertion failed
test(123)           // assertion failed
test(0)             // assertion failed
test(/some regex/)  
test([ 5, 6 ])      // assertion failed
test({ a: 1 })      // assertion failed
test(x => x + 1)    // assertion failed

То же самое для объекта -

Object(x) === x // true, if x is an object
                // false in every other case

NB, регулярные выражения, массивы и функции тоже считаются объектами.

const test = x =>
  console.assert
    ( Object(x) === x
    , `not an object: ${x}`
    )

test("some string") // assertion failed
test(123)           // assertion failed
test(0)             // assertion failed
test(/some regex/)  
test([ 5, 6 ])      
test({ a: 1 })      
test(x => x + 1)    

Но проверка на Array немного отличается -

Array.isArray(x) === x // true, if x is an array
                       // false in every other case

const test = x =>
  console.assert
    ( Array.isArray(x)
    , `not an array: ${x}`
    )

test("some string") // assertion failed
test(123)           // assertion failed
test(0)             // assertion failed
test(/some regex/)  // assertion failed
test([ 5, 6 ])      
test({ a: 1 })      // assertion failed
test(x => x + 1)    // assertion failed

Этот метод не работает для функций, однако -

Function(x) === x // always false
Спасибо
источник
var x = new String(x); String(x)===xвозвращает ложь однако ({}).toString.call(x).search(/String/)>0всегда возвращается для тяжелых вещей
несинхронизировано
1
function isClass(x,re){return ({}).toString.call(x).search(re)>0;}; isClass("hello",/String/) или isClass(3,/Number/)илиisClass(null,/Null/)
несинхронизировано
2

Простое решение будет:

var x = "hello"

if(x === x.toString()){
// it's a string 
}else{
// it isn't
}
Норис
источник
1
это не проверяет, является ли это строкой. Это превращает в строку, многие вещи имеют toString()функцию
Мухаммед Умер
7
@MuhammadUmer Да, он преобразует его в строку, но затем проверяет идентичность исходного значения, которое будет истинным, только если исходное значение также является строкой.
MrWhite
4
это неправильно: вы не можете слепо вызывать .toStringлюбые значения; попробуйте, если проверяемый x равен нулю или не определен, исключение
выдает
1
Идея все еще пригодна для использования. x === Строка (x) безопасна и работает.
Мартон Сари
В самом деле? Это решение кажется мне слишком странным, потому что toString()метод может быть переопределен и может вызвать исключение (из-за некоторой конкретной реализации), и ваша проверка не будет работать наверняка. Основная идея заключается в том, что вы не должны вызывать методы, которые не связаны с тем, что вы хотите получить. Я даже не говорю о ненужных накладных расходах, связанных с toStringметодом. Downvoting.
Рустем Зиннатуллин
2

Помощник Typechecker:

function isFromType(variable, type){
  if (typeof type == 'string') res = (typeof variable == type.toLowerCase())
  else res = (variable.constructor == type)
  return res
}

Применение:

isFromType('cs', 'string') //true
isFromType('cs', String) //true
isFromType(['cs'], Array) //true
isFromType(['cs'], 'object') //false

Также, если вы хотите, чтобы он был рекурсивным (например, Array, который является объектом), вы можете использовать instanceof .

( ['cs'] instanceof Object //true)

Яя
источник
2

Здесь я собираюсь пойти другим путем, чтобы попытаться определить, является ли переменная определенным типом или членом определенного набора типов.
JS построен на Ducktyping; если что-то крякает как строка, мы можем и должны использовать это как строку.

Это 7строка? Тогда почему /\d/.test(7)работает?
Это {toString:()=>('hello there')}строка? Тогда почему ({toString:()=>('hello there')}) + '\ngeneral kenobi!'работает?
Это не вопросы о SHOULD ли работать выше, дело в том, что они делают.

Итак, я сделал duckyString()функцию.
Ниже я проверяю много случаев, не удовлетворяемых другими ответами. Для каждого кода:

  • устанавливает строковую переменную
  • запускает одинаковую строковую операцию и реальную строку для сравнения выходных данных (доказывая, что они могут рассматриваться как строки)
  • преобразует строку, похожую на строку, в реальную строку, чтобы показать вам duckyString()нормализацию входных данных для кода, который ожидает реальные строки
text = 'hello there';
out(text.replace(/e/g, 'E') + ' ' + 'hello there'.replace(/e/g, 'E'));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');

text = new String('oh my');
out(text.toUpperCase() + ' ' + 'oh my'.toUpperCase());
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');

text = 368;
out((text + ' is a big number') + ' ' + ('368' + ' is a big number'));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');

text = ['\uD83D', '\uDE07'];
out(text[1].charCodeAt(0) + ' ' + '😇'[1].charCodeAt(0));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');

function Text() { this.math = 7; }; Text.prototype = {toString:function() { return this.math + 3 + ''; }}
text = new Text();
out(String.prototype.match.call(text, '0') + ' ' + text.toString().match('0'));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');

Это в том же духе, !!xчто x===trueи тестирование, если что-то похоже на массив, а не требует фактического массива.
объекты jQuery; они массивы? Нет, они достаточно хороши? Да, вы можете просто запустить их через Array.prototypeфункции.
Именно эта гибкость дает JS свою силу, и тестирование на строки делает ваш код менее совместимым.

Результат вышеупомянутого:

hEllo thErE hEllo thErE
Is string? true "hello there"

OH MY OH MY
Is string? true "oh my"

368 is a big number 368 is a big number
Is string? true "368"

56839 56839
Is string? true "😇"

0 0
Is string? true "10"

Итак, все дело в том, почему вы хотите знать, является ли что-то строкой.
Если, как и я, вы пришли сюда из Google и хотели узнать, не было ли что -то похожее на строку , вот ответ.
Это даже не дорого, если вы не работаете с действительно длинными или глубоко вложенными массивами символов.
Это потому, что это все операторы if, а не вызовы функций вроде .toString().
За исключением случаев, когда вы пытаетесь увидеть, является ли массив символов с объектами, которые имеют только toString()многобайтовые или только символы, в этом случае нет другого способа проверить, кроме как создать строку и подсчитать количество символов, которые составляют байты, соответственно

function duckyString(string, normalise, unacceptable) {
    var type = null;
    if (!unacceptable)
        unacceptable = {};
    if (string && !unacceptable.chars && unacceptable.to == null)
        unacceptable.to = string.toString == Array.prototype.toString;

    if (string == null)
        ;

    //tests if `string` just is a string
    else if (
        !unacceptable.is &&
        (typeof string == 'string' || string instanceof String)
    )
        type = 'is';

    //tests if `string + ''` or `/./.test(string)` is valid
    else if (
        !unacceptable.to &&
        string.toString && typeof string.toString == 'function' && string.toString != Object.prototype.toString
    )
        type = 'to';

    //tests if `[...string]` is valid
    else if (
        !unacceptable.chars &&
        (string.length > 0 || string.length == 0)
    ) {
        type = 'chars';
        //for each char
        for (var index = 0; type && index < string.length; ++index) {
            var char = string[index];

            //efficiently get its length
            var length = ((duckyString(char, false, {to:true})) ?
                char :
                duckyString(char, true) || {}
            ).length;

            if (length == 1)
                continue;

            //unicode surrogate-pair support
            char = duckyString(char, true);
            length = String.prototype[Symbol && Symbol.iterator];
            if (!(length = length && length.call(char)) || length.next().done || !length.next().done)
                type = null;
        }
    }

    //return true or false if they dont want to auto-convert to real string
    if (!(type && normalise))
        //return truthy or falsy with <type>/null if they want why it's true
        return (normalise == null) ? type != null : type;

    //perform conversion
    switch (type) {
    case 'is':
        return string;
    case 'to':
        return string.toString();
    case 'chars':
        return Array.from(string).join('');
    }
}

Включены варианты для

  • спросите, какой метод считал это string-y
  • исключить методы обнаружения строк (например, если вам не нравится .toString())

Вот еще тесты, потому что я завершитель:

out('Edge-case testing')
function test(text, options) {
    var result = duckyString(text, false, options);
    text = duckyString(text, true, options);
    out(result + ' ' + ((result) ? '"' + text + '"' : text));
}
test('');
test(null);
test(undefined);
test(0);
test({length:0});
test({'0':'!', length:'1'});
test({});
test(window);
test(false);
test(['hi']);
test(['\uD83D\uDE07']);
test([['1'], 2, new String(3)]);
test([['1'], 2, new String(3)], {chars:true});
  • Все негативные случаи, кажется, объясняются
  • Это должно работать в браузерах> = IE8
  • Массивы символов с поддержкой нескольких байтов в браузерах с поддержкой итераторов строк

Вывод:

Edge-case testing
is ""
null null
null null
to "0"
chars ""
chars "!"
null null
chars ""
to "false"
null null
chars "😇"
chars "123"
to "1,2,3"
Hashbrown
источник
1

Просто чтобы расширить ответ @ DRAX , я бы сделал это:

function isWhitespaceEmptyString(str)
{
    //RETURN:
    //      = 'true' if 'str' is empty string, null, undefined, or consists of white-spaces only
    return str ? !(/\S/.test(str)) : (str === "" || str === null || str === undefined);
}

Он также будет учитывать nulls и undefinedтипы, и будет заботиться о нестроковых типах, таких как 0.

ahmd0
источник
1

Это достаточно хорошо для меня.

ВНИМАНИЕ: Это не идеальное решение. Смотрите внизу моего поста.

Object.prototype.isString = function() { return false; };
String.prototype.isString = function() { return true; };

var isString = function(a) {
  return (a !== null) && (a !== undefined) && a.isString();
};

И вы можете использовать это, как показано ниже.

//return false
isString(null);
isString(void 0);
isString(-123);
isString(0);
isString(true);
isString(false);
isString([]);
isString({});
isString(function() {});
isString(0/0);

//return true
isString("");
isString(new String("ABC"));

ВНИМАНИЕ: Это работает неправильно в случае:

//this is not a string
var obj = {
    //but returns true lol
    isString: function(){ return true; }
}

isString(obj) //should be false, but true
Tomozma
источник
-1

Вы можете использовать эту функцию, чтобы определить тип чего-либо:

var type = function(obj) {
    return Object.prototype.toString.apply(obj).replace(/\[object (.+)\]/i, '$1').toLowerCase();
};

Чтобы проверить, является ли переменная строкой:

type('my string') === 'string' //true
type(new String('my string')) === 'string' //true
type(`my string`) === 'string' //true
type(12345) === 'string' //false
type({}) === 'string' // false

https://codepen.io/patodiblasi/pen/NQXPwY?editors=0012

Пато
источник
-2

Я не уверен, что вы имеете в виду, зная, является ли он типом stringнезависимо от его содержимого, или является ли он числом или строкой, независимо от его типа.

Итак, чтобы узнать, является ли его тип строкой, на это уже дан ответ.
Но чтобы узнать на основе его содержимого, является ли оно строкой или числом, я бы использовал это:

function isNumber(item) {
    return (parseInt(item) + '') === item;
}

И для некоторых примеров:

isNumber(123);   //true
isNumber('123'); //true
isNumber('123a');//false
isNumber('');    //false
Арье Бейтц
источник
Я думаю, что первоначально спрашивал, как проверить тип, хотя я тогда не знал, как вообще сформировать вопрос. (и я бы, вероятно, просто сделал это, /^\d+$/.test('123')чтобы избежать сложностей потенциальных проблем с синтаксическим
анализом