Ответы:
Вы можете использовать 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] . Посмотрите другие ответы о том, как справиться с этим, если вы этого хотите.
new String('foo')
, но это не имеет значения, потому что строки, обернутые в объект, являются бесполезной функцией, которую вы не должны использовать. Руководство по стилю Google запрещает их , Дуглас Крокфорд хочет, чтобы они устарели , а библиотеки их не используют. Притворяться, что они не существуют, и использовать typeof
без страха.
Это то, что работает для меня:
if (typeof myVar === 'string' || myVar instanceof String)
// it's a string
else
// it's something else
instanceof
проверка здесь - бессмысленный шум, если вы не следуете некоторым очень необычным методам кодирования, и этот ответ не объясняет, что он делает или почему вы можете его использовать. Единственная причина, по которой вам когда-либо это понадобится, это если вы используете строки, обернутые объектами, но строки, обернутые объектами, - бесполезная функция, которую никто не использует, и Google и Крокфорд оба осуждают как плохую практику ( google-styleguide.googlecode.com/svn/ trunk /… , crockford.com/javascript/recommend.html ).
typeof
и instanceof
чувствует , как хороший совет , если ваш код может быть вызван другими. Крайний postmessage
случай @ MarkAmery имеет значение, если вы спрашиваете: «Что я только что сделал postmessage
?» - но вы ожидаете, что это будет обработано на интерфейсе и не разрешено распространяться. В других местах кажется правильным работать с не осуждаемыми методами кодирования, даже если некоторые эстетики JS их не одобряют. НИКОГДА не комментируйте ваш код как принимающий String, если это не так!
Поскольку более 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))
global || window
вместо него, window
но это будет плохой подход для решения проблемы, которую вы не должны иметь в первую очередь).
myObject+"" === myObject
чтобы проверить, является ли объект строкой (или, что еще лучше, я бы не стал проверять тип в первую очередь в управляемой поведением системе типов).
toString
в Object.prototype
. Итак, я бы сказал, что полагаться на toString
проверку типа объекта - это, в лучшем случае, плохая практика.
Я рекомендую использовать встроенные функции из 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 () для более подробной информации.
_.every()
поначалу это немного сбивает с толку, и что-то столь же простое, как _.isBoolean()
запутало разработчиков в моей компании. Разработчик ошибочно полагал, что будет ложным, если значение будет логическим и будет ложным. Английский для меня легче читать, чем немецкий, потому что я не знаю немецкий. Изучайте JavaScript, и все это будет иметь смысл.
function isString (obj) {
return (Object.prototype.toString.call(obj) === '[object String]');
}
Я видел это здесь:
http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
Object.prototype.toString.call(obj) === '[object String]'
?
(x === y)
имеет лучшую читаемость, чем x === y
?
Лучший способ:
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: «Если он выглядит как утка, ходит как утка и пахнет как утка - это должен быть массив». Проверьте значения.
Надеюсь это поможет.
Помните, что вы всегда можете использовать комбинации подходов. Вот пример использования встроенной карты действий с 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
. Другими словами, мы даже не заботились какой у него был тип.
Надеюсь, это даст вам больше возможностей для работы :)
(o.constructor === Number || s.constructor === Boolean)
). Анекдотично, parseInt
и NaN
хрупкие, но мощные инструменты. Просто помните, что Not-a-Number - это НЕ Not-a-Number, и можно определить undefined.
if(thing.call) { 'its a function'; }
или if(thing.defineProperties) { 'its an object'; }
. Спасибо за вклад, axkibe!
Я не могу честно понять, почему нельзя просто использовать 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'));
Мне нравится использовать это простое решение:
var myString = "test";
if(myString.constructor === String)
{
//It's a string
}
undefined
и null
, и все же получение правильного ответа для пустых строк (как ''
и new String('')
).
(mystring || false) && mystring.constructor === String
. Я использовал false в случае, если он используется в функции, которая должна возвращать логическое значение.
Это отличный пример того, почему производительность имеет значение:
Выполнение чего-либо столь же простого, как тест на строку, может быть дорогостоящим, если не выполнено правильно.
Например, если бы я хотел написать функцию для проверки, является ли что-то строкой, я мог бы сделать это одним из двух способов:
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
typeof str === 'string' || str instanceof String
(могу опустить скобки, которые я предпочитаю в if (..)
случаях); независимо от того, проверка как примитивных, так и объектных типов в # 2 ясна и достаточна. Эти проверки должны быть «редкими» в любом случае.
if (s && typeof s.valueOf() === "string") {
// s is a string
}
Работает как для строковых литералов, так let s = 'blah'
и для объектных строкlet s = new String('blah')
Взято из Лодаш:
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
Я думаю, что решения @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)
И с простой связкой у вас все должно быть в порядке (я ссылаюсь здесь на код клиента).
Я также обнаружил, что это тоже хорошо работает и намного короче, чем другие примеры.
if (myVar === myVar + '') {
//its string
} else {
//its something else
}
Конкатенация в пустых кавычках превращает значение в строку. Если myVar
это уже строка, то оператор if успешен.
typeof
.
typeof
но все же немного быстрее, чем toString
. В любом случае, я думаю, мне просто нравится синтаксис для принуждения.
var s = new String('abc'); > s === s + '' > false
new String
cus, который создает тип object
. w3schools.com/js/tryit.asp?filename=tryjs_string_object2
Если вы работаете в среде node.js, вы можете просто использовать встроенную функцию isString в утилитах.
const util = require('util');
if (util.isString(myVar)) {}
Редактировать: как уже упоминалось @Jehy, это устарело начиная с v4.
typeof value === 'string'
вместо».
x = new String('x'); x.isString(x);
возвращает ложь . Существует, util.types.isStringObject()
но это возвращает ложь для x = 'x'
типа строки. Две служебные функции, которые не предоставляют никакой полезности ...
Следующий метод проверяет, является ли какая-либо переменная строкой ( включая переменные, которые не существуют ).
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
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))
false
.
Я считаю эту простую технику полезной для проверки типов для 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
всегда возвращается для тяжелых вещей
function isClass(x,re){return ({}).toString.call(x).search(re)>0;};
isClass("hello",/String/)
или isClass(3,/Number/)
илиisClass(null,/Null/)
Простое решение будет:
var x = "hello"
if(x === x.toString()){
// it's a string
}else{
// it isn't
}
toString()
функцию
.toString
любые значения; попробуйте, если проверяемый x равен нулю или не определен, исключение
toString()
метод может быть переопределен и может вызвать исключение (из-за некоторой конкретной реализации), и ваша проверка не будет работать наверняка. Основная идея заключается в том, что вы не должны вызывать методы, которые не связаны с тем, что вы хотите получить. Я даже не говорю о ненужных накладных расходах, связанных с toString
методом. Downvoting.
Помощник 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
)
Здесь я собираюсь пойти другим путем, чтобы попытаться определить, является ли переменная определенным типом или членом определенного набора типов.
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('');
}
}
Включены варианты для
.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});
Вывод:
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"
Просто чтобы расширить ответ @ 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
s и undefined
типы, и будет заботиться о нестроковых типах, таких как 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
Вы можете использовать эту функцию, чтобы определить тип чего-либо:
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
Я не уверен, что вы имеете в виду, зная, является ли он типом string
независимо от его содержимого, или является ли он числом или строкой, независимо от его типа.
Итак, чтобы узнать, является ли его тип строкой, на это уже дан ответ.
Но чтобы узнать на основе его содержимого, является ли оно строкой или числом, я бы использовал это:
function isNumber(item) {
return (parseInt(item) + '') === item;
}
И для некоторых примеров:
isNumber(123); //true
isNumber('123'); //true
isNumber('123a');//false
isNumber(''); //false
/^\d+$/.test('123')
чтобы избежать сложностей потенциальных проблем с синтаксическим