Verifique se uma variável é uma string em JavaScript

1742

Como posso determinar se uma variável é uma string ou algo mais em JavaScript?

Olical
fonte

Respostas:

1692

Você pode usar o typeofoperador:

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.


  1. O Google JavaScript Style Guide diz para nunca usar wrappers de objetos primitivos .
  2. Douglas Crockford recomendou que os invólucros de objetos primitivos fossem descontinuados .
Pablo Santa Cruz
fonte
45
@ Wolfy87 Tenha em atenção que existem alguns casos em que typeof stringValue pode devolver "object" em vez de "string". Veja os comentários na minha resposta.
DRAX 26/04/12
163
Minha resposta preferida. O argumento contra isso é que ele "falha" para seqüências de caracteres agrupadas por objeto 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 typeofsem medo.
Mark Amery
2
@ DanielLe, porque ele propôs uma substituição que corrige alguns problemas, não porque ele é contra, em princípio.
Vsevolod Golovanov
4
Se isso lhe causa dores de cabeça, 99,99% das vezes é porque você não estruturou seu código corretamente. Isso não é culpa do NaN por existir e fazer o que faz, é algo que você deve anotar, aprender e ter em mente na próxima vez que trabalhar com código que possa render isso.
Mike 'Pomax' Kamermans
1909

Isto é o que funciona para mim:

if (typeof myVar === 'string' || myVar instanceof String)
// it's a string
else
// it's something else
DRAX
fonte
77
"MyVar instanceof String" faz algo acima e além de "typeof myVar == 'string'"?
svth
81
@svth eu lembrei. Em JavaScript, você pode ter um tipo variável de string ou tipo de objeto que é a classe de String (a mesma coisa - ambas são strings - mas são definidas de maneira diferente), por isso é verificado duas vezes.
DRAX
38
var somevar = new String ('somestring') console.log (typeof somevar) // objeto
Danubian Sailor
82
-1 porque a instanceofverificaçã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 ).
Mark Amery
79
Discordo veementemente que escrever código sólido que lide corretamente com casos improváveis ​​é algo a ser evitado. Verificar os dois typeofe instanceofparecer um bom conselho se o seu código puder ser chamado por outros. @ O postmessagecaso 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!
Dewi Morgan
157

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))

Orwellophile
fonte
11
Você recomenda underscore.js (por qual motivo estranho?), Mas não o usa aqui. Além disso, você polui o espaço de nomes global com funções. No node.js, você criaria um módulo que teria todas essas funções (você pode usar em global || windowvez de, windowmas isso seria uma péssima abordagem para resolver um problema que você não deveria ter em primeiro lugar).
Benjamin Gruenbaum
19
@BenjaminGruenbaum Vim procurar a resposta para a pergunta do OP e não gostei de nenhuma das respostas. Então, verifiquei o que o sublinhado fez e achei que era bacana o suficiente para extrair e modificar um pouco (para evitar ter que carregar a biblioteca de sublinhado). Vou esclarecer minha postagem.
Orwellophile
2
@ Orwellophile Cool, entendi agora, sua resposta original foi formulada como se você estivesse sugerindo sublinhado. Pessoalmente, eu apenas verificaria myObject+"" === myObjectse um objeto é uma string (ou melhor ainda, eu não digitaria check-in em um sistema de tipo orientado a comportamento).
Benjamin Gruenbaum
18
@ Orwellophile, como isso é melhor do que a resposta da DRAX?
Pacerier
3
JS suporta macaco patching, por isso é possível redefinir o toStringno Object.prototype. Então, eu argumentaria que confiar na toStringverificação do tipo de um objeto é, na melhor das hipóteses, uma má prática.
Andre Rodrigues
84

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.

ClearCloud8
fonte
97
Isso é essencial para o que há de errado com a comunidade JS - a verificação do tipo primitivo é de uma linha e envolve apenas a construção de linguagem (uma das básicas), mas você recomenda o uso de biblioteca externa. Se alguém já usa uma dessas bibliotecas, pode ser uma boa ideia, mas fazer o download delas apenas para isso, em vez de simplesmente verificar o tipo, é um exagero.
Rafał Wrzeszcz 25/10
5
Eu vou concordar com Rafal. Estou vendo em todos os lugares que melhora a "legibilidade" para usar uma dessas bibliotecas externas. Se você conhece JavaScript, é mais fácil ler isso do que alguma biblioteca externa que você não usou. _.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.
John Harding
20
@ RafałWrzeszcz Essas bibliotecas são bastante usadas e fornecem muitas funcionalidades úteis (e testadas). Especialmente lodash. Eu não recomendaria que alguém baixasse a biblioteca apenas para usá-la nesta solução .... mas eu recomendaria a todos os desenvolvedores de javascript que baixassem esta biblioteca e ver o que estão perdendo. ;)
ClearCloud8
13
Todos vocês estão perdendo o objetivo de uma biblioteca como Lodash: não velocidade. Não é "facilidade de desenvolvimento". O motivo para usar uma biblioteca como o Lodash fornece "defesa" contra problemas que explodirão seu aplicativo js. Erros fatais ocorrem quando você tenta executar operações de seqüência de caracteres em um objeto (ou vice-versa), e o Lodash fornece um valor tremendo para evitar esses erros.
random_user_name
1
Lembre-se de que muitas pessoas farão isso em um ambiente de nó ou semelhante a um nó, e muito poucas pessoas usarão o jQuery lá.
Matt Fletcher
35
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/

ling
fonte
4
Eu acho que essa solução é a mais robusta, pois lida com cenários de referência entre quadros / janelas, conforme mencionado na URL fornecida na resposta.
ewh 28/05
1
Ótima resposta, parece que o Underscore.js também usa esse método!
Daan
1
@ling Apenas curioso, por que você coloca parênteses Object.prototype.toString.call(obj) === '[object String]'?
precisa
@ Earlee Você quer dizer que (x === y)tem melhor legibilidade do que x === y?
precisa
@StubbornShowaGuy Na minha opinião, sim. É também sobre consistência. Pessoalmente, sempre uso parênteses ao retornar um valor.
Aquarelle 24/01
28

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.

Editar; 05/05/2016

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 httpfunção como a Number. Em outras palavras, nem nos importamos com o tipo.

Espero que isso lhe dê mais para trabalhar :)

Cody
fonte
Você precisaria de algum outro cheque de números antigos simples, uma vez tentando tirar sua propriedade construtor irá falhar:
@torazaburo Funcionou bem para mim agora no console do Chrome. O que faz você pensar que não vai funcionar?
Mark Amery
2
@torazaburo Você pode querer brincar com as afirmações ( (o.constructor === Number || s.constructor === Boolean)). Anedoticamente, parseInte NaNsã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.
Cody
1
a.constructor === Array é errado e pode falhar algumas vezes, o uso Array.isArray ver web.mit.edu/jwalden/www/isArray.html
axkibe
1
Concordado, isso não é à prova de falhas. Uma maneira melhor é usar as verificações de propriedades - essa é a única maneira verdadeiramente segura contra falhas no momento. Exemplo: if(thing.call) { 'its a function'; }ou if(thing.defineProperties) { 'its an object'; }. Obrigado pela contribuição, axkibe!
Cody
17

Sinceramente, não vejo por que não se usaria typeofneste 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.toStringtruque é 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'));

comando personalizado
fonte
15

Eu gosto de usar esta solução simples:

var myString = "test";
if(myString.constructor === String)
{
     //It's a string
}
ScottyG
fonte
3
Como isso é diferente da resposta de Cody, quatro anos depois?
Jonathan H
3
A resposta de @Sheljohn Cody é ótima. Minha resposta (texto completo) é mais curta e direta ao ponto. Você perguntou ... :)
ScottyG
Como função, isso precisaria de uma maneira de lidar com undefinede null, e ainda obter a resposta certa para cadeias vazias (ambas ''e new String('')).
MikeBeaton
@MikeBeaton Não há problema: (mystring || false) && mystring.constructor === String. Eu usei false, caso seja usado em uma função que deve retornar um booleano.
alans
13

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

Rob Brander
fonte
O link do teste está morto, mas eu acredito em você. Esse tipo de informação é super importante. IMHO, essa deve ser, se não a resposta mais votada, pelo menos o comentário mais votado sobre a resposta principal atual.
Coderer
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.
precisa saber é o seguinte
13
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')

fabricante de rodas
fonte
3
Atenção! Isso falhará em cadeias vazias, pois são falsey.
Philipp Sumi
8

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
Benj Sicam
fonte
Se alguém quer saber a fonte, é github.com/lodash/lodash/blob/master/isString.js
Ricardo Canelas
5

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 Stringobjeto (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).

Erez Cohen
fonte
Por que === quando == é suficiente
zavr 19/04
4

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.

David
fonte
Existe alguma substituição?
Anthony Kong
3
Os documentos dizem "Use em typeof value === 'string'vez disso".
Rogers,
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 ...
spinkus 17/04
4

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
Grant Miller
fonte
3

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 myVarjá é uma sequência, a instrução if é bem-sucedida.

Chris Dolphin
fonte
3
O único problema é que você está coagindo uma variável quando deseja verificar seu tipo. Isso me parece um pouco caro quando comparado com typeof.
Olical 27/09
1
Então sim, você está certo. jsperf disse que era cerca de 20% mais lento do que typeofmas ainda um pouco mais rápido que toString. De qualquer forma, acho que gosto da sintaxe para coagir.
Chris Dolphin
4
isso não funciona com o tipo String; var s = new String('abc'); > s === s + '' > false
user5672998
1
Não funciona com new Stringcus que cria um tipo de object. w3schools.com/js/tryit.asp?filename=tryjs_string_object2
Chris Dolphin (
Bem pensado, mas deixa de fora a caixa de borda de cordas enroladas em objetos.
Anthony Rutledge
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))
Jake
fonte
Por que você precisa procurar nulo ou indefinido se x.constructor === String também retornaria false para nulo ou indefinido?
Jules Manson
1
@JulesManson: Isso geraria um erro, não produziria false.
Ry-
3

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
Obrigado
fonte
var x = new String(x); String(x)===xretorna falso. no entanto, ({}).toString.call(x).search(/String/)>0sempre retorna para coisas difíceis
não sincronizado em
1
function isClass(x,re){return ({}).toString.call(x).search(re)>0;}; isClass("hello",/String/) or isClass(3,/Number/)orisClass(null,/Null/)
unsynchronized
2

Uma solução simples seria:

var x = "hello"

if(x === x.toString()){
// it's a string 
}else{
// it isn't
}
Noris
fonte
1
isso não verifica se é uma string. Faz em uma seqüência, muitas coisas têm toString()função
Muhammad Umer
7
@MuhammadUmer Sim, ele a converte em uma string, mas depois verifica a identidade com relação ao valor original, que só será True se o valor original também for uma string.
MrWhite
4
isso está errado: você não pode chamar cegamente .toStringnenhum valor; tente se o x a ser verificado é nulo ou indefinido, seu código lança exceção
user5672998 6/06
1
A ideia ainda é utilizável. x === A string (x) é segura e funciona.
Márton Sári
Mesmo? Esta solução parece muito estranha para mim, porque 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 toStringmétodo. Downvoting.
Rustem Zinnatullin 28/01
2

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)

yaya
fonte
2

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.

É 7uma 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:

  • define uma variável do tipo string
  • executa uma operação de string idêntica e uma string real para comparar saídas (provando que elas podem ser tratadas como strings)
  • converte o tipo de string em um string real para mostrar duckyString()a normalização de entradas para código que espera strings reais
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');

Isso é da mesma maneira que !!xo contrário x===truee 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.prototypefunçõ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

  • pergunte qual método considerou string-y
  • excluir métodos de detecção de string (por exemplo, se você não gosta .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});
  • Todos os casos negativos parecem ser contabilizados
  • Isso deve ser executado nos navegadores> = IE8
  • Matrizes de caracteres com vários bytes suportados em navegadores com suporte ao iterador de cadeias

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"
Hashbrown
fonte
1

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 nulls e undefinedtipos e cuidará de tipos não-string, como 0.

ahmd0
fonte
1

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
Tomozma
fonte
-1

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

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

Pato
fonte
-2

Não sei se você quer saber se é um tipo, stringindependentemente 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
Aryeh Beitz
fonte
Eu acho que estava perguntando originalmente como verificar o tipo, embora ainda não soubesse como formular a pergunta. (e eu provavelmente só fazer isso com /^\d+$/.test('123')para evitar as complexidades de problemas potenciais de análise)
Olical