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

1317

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

Теги:

21 ответ

1187
Лучший ответ

Вы можете использовать оператор 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. Дуглас Крокфорд рекомендовал, чтобы примитивные объектные обертки были устаревшими.
  • 40
    @ Wolfy87 Обратите внимание, что в некоторых случаях typeof stringValue может возвращать «объект» вместо «строка». Смотрите комментарии к моему ответу.
  • 136
    Мой предпочтительный ответ. Аргумент против этого состоит в том, что он «терпит неудачу» для строк, обернутых объектами, таких как new String('foo') , но это не имеет значения, потому что строки, обернутые объектами, являются бесполезной функцией, которую вы не должны использовать. Руководство по стилю Google запрещает их , Дуглас Крокфорд хочет, чтобы они устарели , и никакие библиотеки их не используют. Притворись, что они не существуют, и используй typeof без страха.
Показать ещё 9 комментариев
1500

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

if (typeof myVar === 'string' || myVar instanceof String)
// it a string
else
// it something else
  • 65
    Делает ли myVar instanceof String что-то помимо «typeof myVar == 'string'"?
  • 0
    Если я не ошибаюсь, typeof возвращает имя типа в виде строки («string», «integer» ...), а instanceof сравнивает фактические типы. Сейчас я не могу вспомнить, но я думаю, что в некоторых случаях typeof может возвращать что-то отличное от «string», и поэтому проверяется дважды.
Показать ещё 28 комментариев
108

Поскольку 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;
}, {});
  • 10
    Вы рекомендуете underscore.js (по какой странной причине?), Но вы не используете его здесь. Более того, вы загрязняете глобальное пространство имен функциями. В node.js вы создадите модуль, который будет иметь все эти функции (вы можете использовать global || window вместо window но это был бы плохой подход для решения проблемы, которую вы не должны иметь в первую очередь).
  • 16
    @BenjaminGruenbaum Я искал ответ на вопрос ОП, и мне не понравился ни один из ответов. Поэтому я проверил, что сделал подчеркивание, и подумал, что это достаточно изящно, чтобы немного извлечь и изменить (чтобы избежать загрузки библиотеки подчеркиваний). Я уточню свой пост.
Показать ещё 15 комментариев
72

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

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

lodash/Underscore.js

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

JQuery

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

Подробнее см. lodash Documentation для _.isString().

Подробнее см. jQuery Documentation для $.type().

  • 67
    Это самое важное, что не так с сообществом JS - проверка на примитивный тип является однострочной и включает только языковую конструкцию (одну из основных), но вы рекомендуете использовать внешнюю библиотеку. Если кто-то уже использует одну из этих библиотек, это может быть хорошей идеей, но загрузка их только для этого вместо простой проверки типа является излишним.
  • 5
    Я собираюсь согласиться с Рафалом. Я вижу везде, что это улучшает "читаемость", чтобы использовать одну из этих внешних библиотек. Если вы знаете JavaScript, то его легче читать, чем какую-то внешнюю библиотеку, которую вы не использовали. _.every() немного сбивает с толку, и что-то такое простое, как _.isBoolean() с толку разработчиков в моей компании. Разработчик ошибочно полагал, что будет ложным, если значение будет логическим и будет ложным. Английский для меня легче читать, чем немецкий, потому что я не знаю немецкий. Изучайте JavaScript, и все это будет иметь смысл.
Показать ещё 5 комментариев
30
function isString (obj) {
  return (Object.prototype.toString.call(obj) === '[object String]');
}

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

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

  • 3
    Я думаю, что это решение является наиболее надежным, поскольку оно обрабатывает перекрестные ссылочные сценарии / кросс-окна, как указано в URL-адресе, указанном в ответе.
  • 1
    Отличный ответ, похоже, Underscore.js также использует этот метод!
Показать ещё 6 комментариев
20

Вы можете использовать этот ресурс с открытым исходным кодом is-string component, чтобы проверить, является ли var строкой, избегая копирования в нее.

Примеры:

 isString(3) // => false
 isString('') // => true

Кроме того, вот как isString был реализован в AngularJS:

function isString(value) {return typeof value === 'string';}
18

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

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: "Если это похоже на утку, ходит как утка и пахнет уткой - это должен быть массив", Значение, проверьте его свойства.

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

Edit; 12/05/2016

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

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-casting" - скорее, "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. Другими словами, нам даже не важно, что это за тип.

Надеюсь, что вам будет больше работать с:)

  • 0
    Вам понадобится другая проверка для простых старых чисел, так как попытка получить их свойство конструктора не удастся:
  • 0
    @torazaburo У меня нормально работало только сейчас в консоли Chrome. Что заставляет вас думать, что это не сработает?
Показать ещё 3 комментария
8

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

var myString = "test";
if(myString.constructor === String)
{
     //It a string
}
  • 1
    Чем это отличается от ответа Коди 4 года спустя?
  • 3
    Ответ @Sheljohn Cody великолепен. Мой ответ (полный текст) короче и прямо к делу. Вы спрашивали... :)
7

Взято из lodash:

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
5

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

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

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

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

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

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

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

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

  • 0
    Тестовая ссылка мертва, но я тебе верю. Такая информация очень важна. ИМХО, это должен быть, если не самый одобренный ответ, по крайней мере наиболее одобренный комментарий к текущему ведущему ответу.
  • 0
    typeof str === 'string' || str instanceof String (можно опустить скобки, которые я предпочитаю в случаях if (..) ); независимо от того, проверка как примитивных, так и типов объектов в # 2 ясна и достаточна. Эти проверки должны быть «редкими» в любом случае.
5

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

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

Изменить: как упоминалось @Jehy, это устарело, поскольку v4.

  • 3
    Устаревший с версии 4 : nodejs.org/api/util.html#util_util_isstring_object
  • 0
    Есть ли замена?
Показать ещё 1 комментарий
4

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

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

Объединяясь в пустые кавычки, он превращает значение в строку. Если myVar уже является строкой, то оператор if будет успешным.

  • 2
    Единственная проблема заключается в том, что вы вызываете переменную, когда хотите проверить ее тип. Это кажется мне немного дороже по сравнению с typeof .
  • 1
    Так что да, ты прав. jsperf сказал, что он работает примерно на 20% медленнее, чем typeof но все же немного быстрее, чем toString . В любом случае, я думаю, мне просто нравится синтаксис для принуждения.
Показать ещё 3 комментария
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))
  • 0
    Зачем вам нужно проверять наличие нуля или неопределенности, если x.constructor === String также возвращает false для нуля или неопределенности?
  • 1
    @JulesManson: Это выдаст ошибку, а не выдаст false .
3

Простое решение:

var x = "hello"

if(x === x.toString(){
// it a string 
}else{
// it isn't
}
  • 0
    это не проверяет, является ли это строкой. Это превращает в строку, у многих вещей есть функция toString()
  • 6
    @MuhammadUmer Да, он преобразует его в строку, но затем проверяет идентичность исходного значения, которое будет истинным, только если исходное значение также является строкой.
Показать ещё 3 комментария
1

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

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
1

Это простой трюк. "using charAt"

var string1 = "hello world";
var string2 = String("hello world");
var string3 = new String("hello world");

(string1.charAt && string2.charAt && string3.charAt) && true == true //true
((1).charAt || ({}).charAt || ([]).charAt ) || false == true // false

вы можете использовать charAt для каждого строкового формата, а другие - false. Но null вызывает ошибки.

1

Полный служебный файл для проверки всех переменных.

Вот полное решение, которое не только дает вам базовую функцию использования, чтобы узнать, является ли значение объектом String или чем-то еще. Плюс некоторые другие хорошие функции.

этот необработанный файл используется в моем этом простом проекте реакции редукции на github Simple React Redux

var Sys = {
    /** This Returns Object Type */
    getType: function(val){
        return Object.prototype.toString.call(val);
    },
    /** This Checks and Return if Object is Defined */
    isDefined: function(val){
        return val !== void 0 || typeof val !== 'undefined';
    }
    /** Run a Map on an Array **/
    map: function(arr,fn){
        var res = [], i=0;
        for( ; i<arr.length; ++i){
            res.push(fn(arr[i], i));
        }
        arr = null;
        return res;
    },
    /** Checks and Return if the prop is Objects own Property */
    hasOwnProp: function(obj, val){
        return Object.prototype.hasOwnProperty.call(obj, val);
    },
    /** Extend properties from extending Object to initial Object */
    extend: function(newObj, oldObj){
        for(var prop in oldObj){
            if(hasOwnProp(oldObj, prop)){
                newObj[prop] = oldObj[prop];
            }
        }
        return newObj;
    } }

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

Вышеприведенный код создаст объект Sys = {} этот метод имеет все функции, такие как getType, isDefined Чтобы использовать их, просто попробуйте вызвать этот метод следующим образом.

if(Sys.isDefined(myVar)){ console.log('myVar is defined'); }else { console.log('no myVar is not defined.');}
//Similar to this 
var myStr = 'You are awesome.. !!';
if(Sys.isString(myStr)){console.log(myStr);}
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);
}

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

0

Я не могу честно понять, почему нельзя просто использовать 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'));
0

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

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

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
0

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

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню