Respostas:
Você pode usar o typeof
operador:
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"
Exemplo desta página da web . (O exemplo foi ligeiramente modificado).
Isso não funcionará como esperado no caso de strings criadas com new String()
, mas isso raramente é usado e recomendado contra [1] [2] . Veja as outras respostas para saber como lidar com elas, se desejar.
new String('foo')
, mas isso não importa porque as seqüências de caracteres agrupadas são um recurso inútil que você não deveria estar usando. O guia de estilo do Google os proíbe , Douglas Crockford os quer reprovados e nenhuma biblioteca os usa. Finja que eles não existem e use typeof
sem medo.
Isto é o que funciona para mim:
if (typeof myVar === 'string' || myVar instanceof String)
// it's a string
else
// it's something else
instanceof
verificação aqui é um ruído inútil, a menos que você esteja seguindo algumas práticas de codificação muito incomuns , e esta resposta não explica nada o que faz ou por que você pode usá-lo. A única razão pela qual você precisaria disso é se você usar seqüências de caracteres agrupadas a objetos, mas essas são um recurso inútil que ninguém usa, e Google e Crockford condenam as práticas recomendadas ( google-styleguide.googlecode.com/svn/ trunk /… , crockford.com/javascript/recommend.html ).
typeof
e instanceof
parecer um bom conselho se o seu código puder ser chamado por outros. @ O postmessage
caso de ponta do MarkAmery importa se você está perguntando "o que eu acabei de fazer postmessage
?" - mas você espera que isso seja tratado na interface e não tenha permissão para se propagar. Em outros lugares, parece correto lidar com métodos de codificação não preteridos, mesmo que alguns esteticistas de JS os desaprovem. NUNCA comente seu código como aceitando String, a menos que realmente aceite!
Como mais de 580 pessoas votaram em uma resposta incorreta e mais de 800 votaram em uma resposta funcional, mas no estilo de espingarda, pensei que poderia valer a pena refazer minha resposta de uma forma mais simples que todos possam entender.
function isString(x) {
return Object.prototype.toString.call(x) === "[object String]"
}
Ou, inline (eu tenho uma configuração do UltiSnip para isso):
Object.prototype.toString.call(myVar) === "[object String]"
Para sua informação, a resposta de Pablo Santa Cruz está errada, porque typeof new String("string")
éobject
A resposta da DRAX é precisa e funcional e deve ser a resposta correta (já que Pablo Santa Cruz está definitivamente definitivamente incorreto, e não vou argumentar contra o voto popular).
No entanto, essa resposta também é definitivamente correta e, na verdade, a melhor resposta (exceto, talvez, a sugestão de usar lodash / sublinhado ). isenção de responsabilidade: eu contribuí para a base de código do lodash 4.
Minha resposta original (que obviamente voou sobre muitas cabeças) é a seguinte:
Eu transcodifiquei isso de underscore.js:
['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'].forEach(
function(name) {
window['is' + name] = function(obj) {
return toString.call(obj) == '[object ' + name + ']';
};
});
Isso definirá isString, isNumber, etc.
No Node.js, isso pode ser implementado como um módulo:
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)
trabalha para delinear também entre funções e funções assíncronas:
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
vez de, window
mas isso seria uma péssima abordagem para resolver um problema que você não deveria ter em primeiro lugar).
myObject+"" === myObject
se um objeto é uma string (ou melhor ainda, eu não digitaria check-in em um sistema de tipo orientado a comportamento).
toString
no Object.prototype
. Então, eu argumentaria que confiar na toString
verificação do tipo de um objeto é, na melhor das hipóteses, uma má prática.
Eu recomendo usar as funções internas do jQuery ou lodash / Underscore . Eles são mais simples de usar e mais fáceis de ler.
Qualquer uma das funções manipulará o caso DRAX mencionado ... ou seja, ambos verificam se (A) a variável é uma string literal ou (B) é uma instância do objeto String. Nos dois casos, essas funções identificam corretamente o valor como sendo uma sequência.
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
Consulte a documentação do lodash para _.isString () para obter mais detalhes.
Veja a documentação do jQuery para $ .type () para mais detalhes.
_.every()
é um pouco confuso para usar no começo, e algo tão simples quanto _.isBoolean()
confundiu desenvolvedores na minha empresa. Um desenvolvedor pensou erroneamente que seria falso se o valor fosse booleano e falso. Inglês é mais fácil de ler do que alemão para mim, porque eu não sei alemão. Aprenda JavaScript e tudo fará sentido.
function isString (obj) {
return (Object.prototype.toString.call(obj) === '[object String]');
}
Eu vi isso aqui:
http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
Object.prototype.toString.call(obj) === '[object String]'
?
(x === y)
tem melhor legibilidade do que x === y
?
Melhor maneira:
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');
Cada um deles foi construído por sua função de classe apropriada, como "new Object ()" etc.
Além disso, digitação de pato: "Se ele se parece com um pato, anda como um pato e cheira a pato - deve ser uma matriz" Significado, verifique suas propriedades.
Espero que isto ajude.
Lembre-se, você sempre pode usar combinações de abordagens também. Aqui está um exemplo do uso de um mapa de ações embutido com typeof :
var type = { 'number': Math.sqrt.bind(Math), ... }[ typeof datum ];
Aqui está um exemplo mais "real" do uso de mapas em linha:
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
Esta função usaria [custom] "conversão de tipo" - em vez disso, "tipo - / - mapeamento de valor" - para descobrir se uma variável realmente "existe". Agora você pode dividir esse cabelo desagradável entre null
& 0
!
Muitas vezes você nem se importa com seu tipo . Outra maneira de contornar a digitação é combinar conjuntos do tipo pato:
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) ...;
}
Ambos Number.prototype
e String.prototype
têm um .toString() method
. Você apenas certificou-se de que o número da string equivalente ao número fosse o mesmo e, em seguida, certificou-se de que o passasse para a http
função como a Number
. Em outras palavras, nem nos importamos com o tipo.
Espero que isso lhe dê mais para trabalhar :)
(o.constructor === Number || s.constructor === Boolean)
). Anedoticamente, parseInt
e NaN
são ferramentas frágeis, mas poderosas. Lembre-se de que Não é um número NÃO é um número e pode ser definido indefinido.
if(thing.call) { 'its a function'; }
ou if(thing.defineProperties) { 'its an object'; }
. Obrigado pela contribuição, axkibe!
Sinceramente, não vejo por que não se usaria typeof
neste caso:
if (typeof str === 'string') {
return 42;
}
Sim, falhará com as seqüências de caracteres agrupadas a objetos (por exemplo new String('foo')
), mas elas são amplamente consideradas como uma prática ruim e a maioria das ferramentas de desenvolvimento modernas provavelmente desencorajará seu uso. (Se você vir um, basta corrigi-lo!)
O Object.prototype.toString
truque é algo que todos os desenvolvedores de front-end foram considerados culpados de fazer um dia em suas carreiras, mas não o deixem enganar por seu polimento inteligente: ele será quebrado assim que algo corrigir o protótipo do Object:
const isString = thing => Object.prototype.toString.call(thing) === '[object String]';
console.log(isString('foo'));
Object.prototype.toString = () => 42;
console.log(isString('foo'));
Eu gosto de usar esta solução simples:
var myString = "test";
if(myString.constructor === String)
{
//It's a string
}
undefined
e null
, e ainda obter a resposta certa para cadeias vazias (ambas ''
e new String('')
).
(mystring || false) && mystring.constructor === String
. Eu usei false, caso seja usado em uma função que deve retornar um booleano.
Este é um ótimo exemplo de por que o desempenho é importante:
Fazer algo simples como um teste para uma string pode ser caro se não for feito corretamente.
Por exemplo, se eu quisesse escrever uma função para testar se algo é uma string, poderia fazê-lo de duas maneiras:
1) const isString = str => (Object.prototype.toString.call(str) === '[object String]');
2) const isString = str => ((typeof str === 'string') || (str instanceof String));
Ambos são bem diretos, então o que poderia impactar o desempenho? De um modo geral, as chamadas de funções podem ser caras, especialmente se você não sabe o que está acontecendo lá dentro. No primeiro exemplo, há uma chamada de função ao método toString do Object. No segundo exemplo, não há chamadas de função, pois typeof e instanceof são operadores. Os operadores são significativamente mais rápidos que as chamadas de função.
Quando o desempenho é testado, o exemplo 1 é 79% mais lento que o exemplo 2!
Veja os testes: https://jsperf.com/isstringtype
typeof str === 'string' || str instanceof String
(pode soltar o parêntese que eu prefiro nos if (..)
casos); independentemente, a verificação dos tipos primitivo e de objeto em # 2 é clara e suficiente. Essas verificações devem ser "raras" de qualquer maneira.
if (s && typeof s.valueOf() === "string") {
// s is a string
}
Funciona para literais de seqüência de caracteres let s = 'blah'
e para seqüências de caracteres de objetolet s = new String('blah')
Retirado de 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
Penso que a solução @customcommander deve ser suficiente em 90% dos seus casos:
typeof str === 'string'
Deve atendê-lo corretamente (simplesmente porque normalmente não há motivo para ter new String('something')
no seu código).
Se você também estiver interessado em manipular o String
objeto (por exemplo, espera alguma var de terceiros), usar o lodash como sugerido pelo @ ClearCloud8 parece uma solução clara, simples e elegante.
No entanto, eu sugeriria ser cauteloso com bibliotecas como a lodash devido ao seu tamanho. Em vez de fazer
import _ from 'lodash'
...
_.isString(myVar)
O que traz todo o enorme objeto lodash, sugiro algo como:
import { isString as _isString } from 'lodash'
...
_isString(myVar)
E com o pacote simples, você deve ficar bem (refiro-me aqui ao código do cliente).
Se você trabalha no ambiente node.js., pode simplesmente usar a função interna isString nos utils.
const util = require('util');
if (util.isString(myVar)) {}
Edit: como @Jehy mencionado, isso está obsoleto desde a v4.
typeof value === 'string'
vez disso".
x = new String('x'); x.isString(x);
retorna falso . Existe, util.types.isStringObject()
porém, que retorna false para o x = 'x'
tipo string. Duas funções utilitárias que não fornecem absolutamente nenhuma utilidade ...
O método a seguir verificará se alguma variável é uma sequência ( incluindo variáveis que não existem ).
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
Também descobri que isso funciona bem também, e é muito mais curto que os outros exemplos.
if (myVar === myVar + '') {
//its string
} else {
//its something else
}
Ao concatenar aspas vazias, ele transforma o valor em uma sequência. Se myVar
já é uma sequência, a instrução if é bem-sucedida.
typeof
.
typeof
mas ainda um pouco mais rápido que toString
. De qualquer forma, acho que gosto da sintaxe para coagir.
var s = new String('abc'); > s === s + '' > false
new String
cus que cria um tipo de object
. w3schools.com/js/tryit.asp?filename=tryjs_string_object2
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
.
Eu acho essa técnica simples útil para verificar o tipo de 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
A mesma técnica também funciona para o Number -
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
E para 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
Mesmo para Objeto -
Object(x) === x // true, if x is an object
// false in every other case
NB, regexps, matrizes e funções também são considerados objetos.
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)
Mas, verificar a matriz é um pouco diferente -
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
Essa técnica não funciona para Funções, no entanto -
Function(x) === x // always false
var x = new String(x); String(x)===x
retorna falso. no entanto, ({}).toString.call(x).search(/String/)>0
sempre retorna para coisas difíceis
function isClass(x,re){return ({}).toString.call(x).search(re)>0;};
isClass("hello",/String/)
or isClass(3,/Number/)
orisClass(null,/Null/)
Uma solução simples seria:
var x = "hello"
if(x === x.toString()){
// it's a string
}else{
// it isn't
}
toString()
função
.toString
nenhum valor; tente se o x a ser verificado é nulo ou indefinido, seu código lança exceção
toString()
método pode ser substituído e pode gerar uma exceção (devido a alguma implementação específica), e sua verificação não funcionará com certeza. A idéia principal é que você não deve chamar métodos que não estejam relacionados ao que você deseja obter. Nem estou falando de sobrecarga desnecessária relacionada ao toString
método. Downvoting.
Um auxiliar Typechecker:
function isFromType(variable, type){
if (typeof type == 'string') res = (typeof variable == type.toLowerCase())
else res = (variable.constructor == type)
return res
}
uso:
isFromType('cs', 'string') //true
isFromType('cs', String) //true
isFromType(['cs'], Array) //true
isFromType(['cs'], 'object') //false
Além disso, se você quiser que seja recursivo (como Matriz que é um Objeto), você pode usar instanceof
.
( ['cs'] instanceof Object //true
)
Vou seguir uma rota diferente para o resto aqui, que tenta dizer se uma variável é um tipo específico, ou membro de um conjunto específico, de tipos.
JS é construído em ducktyping; se algo se intrometer como uma string, podemos e devemos usá-la como uma string.
É 7
uma string? Então, por que /\d/.test(7)
funciona?
É {toString:()=>('hello there')}
uma string? Então, por que ({toString:()=>('hello there')}) + '\ngeneral kenobi!'
funciona?
Estas não são perguntas sobre se o trabalho acima funciona, o ponto é que elas funcionam.
Então, eu fiz uma duckyString()
função.
Abaixo, testo muitos casos não atendidos por outras respostas. Para cada um o código:
duckyString()
a normalização de entradas para código que espera strings reaistext = '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');
Isso é da mesma maneira que !!x
o contrário x===true
e teste se algo é semelhante a um array em vez de precisar de um array real.
objetos jQuery; eles são matrizes? Não. Eles são bons o suficiente? Sim, você pode executá-los através de Array.prototype
funções muito bem.
É essa flexibilidade que dá à JS seu poder, e o teste de strings especificamente torna seu código menos interoperável.
A saída do acima é:
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"
Então, é tudo sobre por que você quer saber se algo é uma string.
Se, como eu, você chegou aqui do Google e queria ver se havia algo parecido com uma corda , aqui está uma resposta.
Não é nem caro, a menos que você esteja trabalhando com matrizes de caracteres muito longas ou profundamente aninhadas.
Isso ocorre porque são todas as declarações if, nenhuma função é chamada .toString()
.
Exceto se você estiver tentando ver se uma matriz de caracteres com objetos que possuem apenas toString()
caracteres de vários bytes ou, nesse caso, não há outra maneira de verificar, exceto para criar a string e contar os caracteres que os bytes compõem, respectivamente
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('');
}
}
Estão incluídas opções para
.toString()
)Aqui estão mais testes porque eu sou um completista:
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});
Resultado:
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"
Apenas para expandir a resposta da @ DRAX , eu faria o seguinte:
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);
}
Ele também será responsável por null
s e undefined
tipos e cuidará de tipos não-string, como 0
.
Isso é bom o suficiente para mim.
AVISO: Esta não é uma solução perfeita. Veja a parte inferior do meu post.
Object.prototype.isString = function() { return false; };
String.prototype.isString = function() { return true; };
var isString = function(a) {
return (a !== null) && (a !== undefined) && a.isString();
};
E você pode usar isso como abaixo.
//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"));
AVISO: Isso funciona incorretamente no caso:
//this is not a string
var obj = {
//but returns true lol
isString: function(){ return true; }
}
isString(obj) //should be false, but true
Você pode usar esta função para determinar o tipo de qualquer coisa:
var type = function(obj) {
return Object.prototype.toString.apply(obj).replace(/\[object (.+)\]/i, '$1').toLowerCase();
};
Para verificar se uma variável é uma sequência:
type('my string') === 'string' //true
type(new String('my string')) === 'string' //true
type(`my string`) === 'string' //true
type(12345) === 'string' //false
type({}) === 'string' // false
Não sei se você quer saber se é um tipo, string
independentemente de seu conteúdo, ou se é um número ou sequência de caracteres, independentemente de seu tipo.
Portanto, para saber se seu tipo é uma sequência, isso já foi respondido.
Mas, para saber, com base em seu conteúdo, se é uma string ou um número, eu usaria isso:
function isNumber(item) {
return (parseInt(item) + '') === item;
}
E para alguns exemplos:
isNumber(123); //true
isNumber('123'); //true
isNumber('123a');//false
isNumber(''); //false
/^\d+$/.test('123')
para evitar as complexidades de problemas potenciais de análise)