Compruebe si una variable es una cadena en JavaScript


1744

¿Cómo puedo determinar si una variable es una cadena o algo más en JavaScript?

Respuestas:


1692

Puedes usar el 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"

Ejemplo de esta página web . (Sin embargo, el ejemplo fue ligeramente modificado).

Esto no funcionará como se espera en el caso de las cadenas creadas con new String(), pero esto rara vez se usa y se recomienda contra [1] [2] . Vea las otras respuestas sobre cómo manejarlas, si así lo desea.


  1. La Guía de estilo de JavaScript de Google dice que nunca use envoltorios de objetos primitivos .
  2. Douglas Crockford recomendó que los envoltorios de objetos primitivos sean obsoletos .

45
@ Wolfy87 Tenga en cuenta que hay algunos casos en que typeof stringValue podría devolver "objeto" en lugar de "cadena". Ver comentarios en mi respuesta.
DRAX

163
Mi respuesta preferida El argumento en contra es que 'falla' para cadenas envueltas en objetos como new String('foo'), pero eso no importa porque las cadenas envueltas en objetos son una característica inútil que no debería usar. La guía de estilo de Google los prohíbe , Douglas Crockford quiere que sean desaprobados , y ninguna biblioteca los usa. Finge que no existen y úsalo typeofsin miedo.
Mark Amery


2
@DanielLe, porque propuso un reemplazo que soluciona algunos problemas, no porque esté en contra en principio.
Vsevolod Golovanov

44
Si le causa dolores de cabeza, el 99.99% del tiempo se debe a que no estructuró su código correctamente. Eso no es culpa de NaN por existir y hacer lo que hace, eso es algo que debe tener en cuenta, aprender y tener en cuenta la próxima vez que trabaje con código que pueda generarlo.
Mike 'Pomax' Kamermans

1911

Esto es lo que funciona para mí:

if (typeof myVar === 'string' || myVar instanceof String)
// it's a string
else
// it's something else

77
¿"MyVar instanceof String" hace algo más allá de "typeof myVar == 'string'"?
svth

81
@svth lo recordaba. En JavaScript, puede tener un tipo variable de cadena o un tipo de objeto que es una clase de cadena (lo mismo, ambas son cadenas, pero se definen de manera diferente), por eso se verifica dos veces.
DRAX

38
var somevar = new String ('somestring') console.log (typeof somevar) // object
Danubian Sailor

82
-1 porque la instanceofcomprobación aquí es ruido sin sentido a menos que esté siguiendo algunas prácticas de codificación muy inusuales , y esta respuesta no hace nada para explicar lo que hace o por qué podría usarlo. La única razón por la que lo necesitaría es si usa cadenas envueltas en objetos, pero las cadenas envueltas en objetos son una característica inútil que nadie usa y Google y Crockford condenan como una mala práctica ( google-styleguide.googlecode.com/svn/ trunk / ... , crockford.com/javascript/recommend.html ).
Mark Amery

79
Estoy totalmente en desacuerdo con que escribir código sólido que maneja correctamente casos improbables es algo que se debe evitar. Verifica ambos typeofy instanceofparece un buen consejo si su código puede ser llamado por otros '. El postmessagecaso marginal de @ MarkAmery importa si preguntas "¿qué era lo que acabo de decir postmessage?" - pero esperaría que se maneje en la interfaz y no se permita su propagación. En otros lugares, parece correcto manejar métodos de codificación no obsoletos, incluso si algunos estéticos de JS los desaprueban. ¡NUNCA comente su código como aceptando String, a menos que realmente lo haga!
Dewi Morgan

157

Dado que más de 580 personas votaron por una respuesta incorrecta, y más de 800 votaron por una respuesta funcional pero de estilo escopeta, pensé que valdría la pena rehacer mi respuesta en una forma más simple que todos puedan entender.

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

O en línea (tengo una configuración de UltiSnip para esto):

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

Para su información, la respuesta de Pablo Santa Cruz es incorrecta, porque typeof new String("string") esobject

La respuesta de DRAX es precisa y funcional, y debería ser la respuesta correcta (ya que Pablo Santa Cruz es definitivamente incorrecto, y no discutiré en contra del voto popular).

Sin embargo, esta respuesta también es definitivamente correcta, y en realidad es la mejor respuesta (excepto, tal vez, por la sugerencia de usar lodash / subrayado ).descargo de responsabilidad: contribuí a la base de código lodash 4.

Mi respuesta original (que obviamente voló sobre muchas cabezas) es la siguiente:

Transcodifiqué esto de underscore.js:

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

Eso definirá isString, isNumber, etc.


En Node.js, esto se puede implementar como un módulo:

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

[editar]: Object.prototype.toString.call(x)funciona para delinear entre funciones y funciones asíncronas también:

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


11
Recomienda underscore.js (¿por qué razón extraña?) Pero no lo usa aquí. Además, contamina el espacio de nombres global con funciones. En node.js crearía un módulo que tendría todas estas funciones ( puede usar en global || windowlugar de, windowpero sería un mal enfoque para resolver un problema que no debería tener en primer lugar).
Benjamin Gruenbaum

19
@BenjaminGruenbaum Vine buscando la respuesta a la pregunta del OP, y no me gustó ninguna de las respuestas. Así que verifiqué lo que hacía el subrayado, y pensé que era lo suficientemente ingenioso para extraer y modificar un poco (para evitar tener que cargar la biblioteca de subrayado). Aclararé mi publicación.
Orwellophile

2
@Orwellophile Cool, lo entiendo ahora, tu respuesta original fue redactada como si estuvieras sugiriendo un subrayado. Personalmente, solo verificaría myObject+"" === myObjectpara verificar si un objeto es una cadena (o mejor aún, no escribiría check en un sistema de tipo basado en el comportamiento en primer lugar).
Benjamin Gruenbaum

18
@Orwellophile, ¿cómo es esto mejor que la respuesta de DRAX?
Pacerier

3
JS admite parches de mono, por lo que es posible redefinir el toStringen el Object.prototype. Entonces, argumentaría que confiar en toStringverificar el tipo de un objeto es, en el mejor de los casos, una mala práctica.
Andre Rodrigues

84

Recomiendo usar las funciones integradas de jQuery o lodash / Underscore . Son más simples de usar y más fáciles de leer.

Cualquiera de las funciones manejará el caso mencionado por DRAX ... es decir, ambos verifican si (A) la variable es un literal de cadena o (B) es una instancia del objeto String. En cualquier caso, estas funciones identifican correctamente el valor como una cadena.

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 la documentación de lodash para _.isString () para obtener más detalles.

Ver documentación de jQuery para $ .type () para obtener más detalles.


97
Esto es lo esencial de lo que está mal con la comunidad JS: la verificación contra el tipo primitivo es de una sola línea e implica solo la construcción del lenguaje (uno de los básicos), pero recomienda usar una biblioteca externa. Si alguien ya usa una de estas bibliotecas, puede ser una buena idea, pero descargarlas solo por eso en lugar de simplemente verificar el tipo es una exageración.
Rafał Wrzeszcz

55
Voy a estar de acuerdo con Rafal. Veo en todas partes que mejora la "legibilidad" para usar una de estas bibliotecas externas. Si conoce JavaScript, entonces es más fácil de leer que algunas bibliotecas externas que no ha utilizado. _.every()es un poco confuso de usar al principio, y algo tan simple como _.isBoolean()ha confundido a los desarrolladores de mi empresa. Un desarrollador erróneamente pensó que sería falso si el valor era booleano y era falso. El inglés es más fácil de leer que el alemán para mí, porque no sé alemán. Aprenda JavaScript y todo tendrá sentido.
John Harding

20
@ RafałWrzeszcz Estas bibliotecas son bastante utilizadas y proporcionan una funcionalidad muy útil (y probada). Especialmente lodash. No recomendaría que alguien descargue la biblioteca solo para usarla con esta solución ... pero recomendaría a todos los desarrolladores de JavaScript que descarguen esta biblioteca y vean qué se están perdiendo. ;)
ClearCloud8

13
A todos les falta el punto de una biblioteca como Lodash: no la velocidad. No es "facilidad de desarrollo". La razón para usar una biblioteca como Lodash proporciona "defensa" contra los problemas que harán explotar su aplicación js. Los errores fatales suceden cuando intenta realizar operaciones de cadena en un objeto (o viceversa), y Lodash proporciona un gran valor para evitar esos errores.
random_user_name

1
Tenga en cuenta que muchas personas harán esto en un entorno Node o similar a Node, y muy pocas personas usarán jQuery allí.
Matt Fletcher el

35
function isString (obj) {
  return (Object.prototype.toString.call(obj) === '[object String]');
}

Vi eso aquí:

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


44
Creo que esta solución es la más sólida, ya que maneja escenarios de referencia de marco cruzado / ventana cruzada como se menciona en la URL proporcionada en la respuesta.
ewh

1
Gran respuesta, ¡parece que Underscore.js también usa este método!
Daan

1
@ling Por curiosidad, ¿por qué pones paréntesis Object.prototype.toString.call(obj) === '[object String]'?
StubbornShowaGuy

@Earlee ¿Quieres decir que (x === y)tiene mejor legibilidad que x === y?
StubbornShowaGuy

@StubbornShowaGuy En mi opinión, sí. También se trata de consistencia. Yo personalmente siempre uso paréntesis cuando devuelvo un valor.
Aquarelle

28

Mejor manera:

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 uno de estos ha sido construido por su función de clase apropiada, como "new Object ()", etc.

Además, Duck-Typing: "Si parece un pato, camina como un pato y huele a pato, debe ser una matriz", lo que significa que compruebe sus propiedades.

Espero que esto ayude.

Editar; 12/05/2016

Recuerde, siempre puede usar combinaciones de enfoques también. Aquí hay un ejemplo del uso de un mapa en línea de acciones con typeof :

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

Aquí hay un ejemplo más 'real' del uso de mapas en línea:

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 función usaría "conversión de tipo" [personalizada] - en lugar de "tipo - / - mapeo de valores" - para determinar si una variable realmente "existe". ¡Ahora puedes dividir ese cabello desagradable entre null& 0!

Muchas veces ni siquiera te importa su tipo . Otra forma de evitar el tipeo es combinar conjuntos de 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 y String.prototype tienen un .toString() method. Simplemente se aseguró de que el equivalente de cadena del número fuera el mismo, y luego se aseguró de pasarlo a la httpfunción como a Number. En otras palabras, ni siquiera nos importaba cuál era su tipo.

Espero que te dé más para trabajar :)


Necesitaría alguna otra verificación para los números antiguos simples, ya que tratará de tomar su propiedad de constructor fallará:

@torazaburo Funcionó bien para mí justo ahora en la consola de Chrome. ¿Qué te hace pensar que no funcionará?
Mark Amery

2
@torazaburo Es posible que desee jugar con las afirmaciones ( (o.constructor === Number || s.constructor === Boolean)). Anecdóticamente,parseInt y NaNson herramientas frágiles pero poderosas. Solo recuerde que Not-a-Number NO es Not-a-Number y se puede definir indefinido.
Cody

1
a.constructor === La matriz está mal y puede fallar a veces, use Array.isArray, consulte web.mit.edu/jwalden/www/isArray.html
axkibe

1
De acuerdo, esto no es a prueba de fallas. Una mejor manera es usar controles de propiedad: ESA es la única forma verdaderamente segura en este momento. Ejemplo: if(thing.call) { 'its a function'; }o if(thing.defineProperties) { 'its an object'; }. Gracias por el aporte, axkibe!
Cody

17

Honestamente, no puedo ver por qué uno no usaría simplemente typeofen este caso:

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

Sí, fallará contra las cadenas envueltas en objetos (por ejemplo new String('foo')), pero estas son ampliamente consideradas como una mala práctica y es probable que la mayoría de las herramientas de desarrollo modernas desalienten su uso. (Si ves uno, ¡solo arréglalo!)

los Object.prototype.toString truco es algo que todos los desarrolladores front-end han sido declarados culpables de hacer un día en sus carreras, pero no dejes que te engañe por su pulido de inteligencia: se romperá tan pronto como algo parchee el prototipo de Object:

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

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

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

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


15

Me gusta usar esta solución simple:

var myString = "test";
if(myString.constructor === String)
{
     //It's a string
}

3
¿Cómo es eso diferente de la respuesta de Cody, 4 años después?
Jonathan H

3
La respuesta de @Sheljohn Cody es genial. Mi respuesta (texto completo) es más corta y directa al grano. Usted preguntó ... :)
ScottyG

Como función, esto necesitaría una forma de tratar con undefinedy null, y aún así obtener la respuesta correcta para cadenas vacías (ambos ''y new String('')).
MikeBeaton

@MikeBeaton No hay problema: (mystring || false) && mystring.constructor === String. Usé falso en caso de que se use en una función que debe devolver un valor booleano.
Alans

13

Este es un gran ejemplo de por qué el rendimiento es importante:

Hacer algo tan simple como una prueba para una cadena puede ser costoso si no se hace correctamente.

Por ejemplo, si quisiera escribir una función para probar si algo es una cadena, podría hacerlo de dos maneras:

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

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

Ambos son bastante sencillos, entonces, ¿qué podría afectar el rendimiento? En términos generales, las llamadas a funciones pueden ser costosas, especialmente si no sabe lo que sucede dentro. En el primer ejemplo, hay una llamada de función al método toString de Object. En el segundo ejemplo, no hay llamadas a funciones, ya que typeof e instanceof son operadores. Los operadores son significativamente más rápidos que las llamadas a funciones.

Cuando se prueba el rendimiento, el ejemplo 1 es un 79% más lento que el ejemplo 2.

Ver las pruebas: https://jsperf.com/isstringtype


El enlace de prueba está muerto, pero te creo. Este tipo de información es muy importante. En mi humilde opinión, esta debería ser, si no la respuesta más votada, al menos el comentario más votado sobre la respuesta principal actual.
Coderer el

typeof str === 'string' || str instanceof String(puede quitar el paréntesis que prefiero en los if (..)casos); de todos modos, verificar tanto los tipos primitivos como los de objeto en el n. ° 2 es claro y suficiente. Estas comprobaciones deberían ser "raras" de todos modos.
user2864740

13
if (s && typeof s.valueOf() === "string") {
  // s is a string
}

Funciona tanto para literales de cadena let s = 'blah'como para cadenas de objetolet s = new String('blah')


3
¡Atención! Esto fallará en cadenas vacías, ya que son falsey.
Philipp Sumi

8

Tomado 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

Si alguien quiere conocer la fuente, es github.com/lodash/lodash/blob/master/isString.js
Ricardo Canelas

5

Creo que la solución @customcommander debería ser suficiente en el 90% de sus casos:

typeof str === 'string'

Debería servirle bien (simplemente porque normalmente no hay razón para tener new String('something') en su código).

Si estás interesado en manejar el String objeto (por ejemplo, espera algunas variaciones de un tercero), usar lodash como sugiere @ ClearCloud8 parece una solución clara, simple y elegante.

Sin embargo, sugeriría ser cauteloso con las bibliotecas como lodash debido a su tamaño. En lugar de hacer

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

Lo que trae todo el enorme objeto lodash, sugeriría algo como:

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

Y con un paquete simple debería estar bien (me refiero aquí al código del cliente).


por qué === cuando == es suficiente
zavr

4

Si trabaja en el entorno node.js, simplemente puede usar la función integrada isString en utils.

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

Editar: como mencionó @Jehy, esto está en desuso desde v4.


¿Hay algún reemplazo?
Anthony Kong

3
Los documentos dicen "Usar en su typeof value === 'string'lugar".
Sr. Rogers

x = new String('x'); x.isString(x);devuelve falso . Hay util.types.isStringObject()pero eso devuelve falso para el x = 'x'tipo cadena. Dos funciones de utilidad que no proporcionan absolutamente ninguna utilidad ...
spinkus

4

El siguiente método verificará si alguna variable es una cadena ( incluidas las variables que no existen ).

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

let example = 'Hello, world!';

console.log(is_string(() => example)); // true
console.log(is_string(() => variable_doesnt_exist)); // false

3

También descubrí que esto también funciona bien, y es mucho más corto que los otros ejemplos.

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

Al concatenar entre comillas vacías, convierte el valor en una cadena. Si myVarya es una cadena, la instrucción if es exitosa.


3
El único problema es que estás coaccionando una variable cuando quieres verificar su tipo. Eso me parece un poco caro en comparación con typeof.
Olical

1
Entonces sí, tienes razón. jsperf dijo que era un 20% más lento que, typeofpero aún bastante más rápido que toString. De cualquier manera, supongo que me gusta la sintaxis para coaccionar.
Chris Dolphin

44
esto no funciona con el tipo String; var s = new String('abc'); > s === s + '' > false
user5672998

1
No funciona con new Stringcus que crea un tipo de object. w3schools.com/js/tryit.asp?filename=tryjs_string_object2
Chris Dolphin el

Buen pensamiento, pero deja de lado el caso de las cadenas envueltas en 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))

¿Por qué necesita verificar nulo o indefinido si x.constructor === String también devolvería falso para nulo o indefinido?
Jules Manson el

1
@JulesManson: arrojaría un error, no produciría false.
Ry-

3

Me parece útil esta técnica simple para verificar el 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

La misma técnica también funciona para 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

Y 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

Lo mismo para objetos -

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

NB, regexps, matrices y funciones también se consideran 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)    

Pero, verificar Array es un poco 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

Sin embargo, esta técnica no funciona para las funciones :

Function(x) === x // always false

var x = new String(x); String(x)===xdevuelve falso sin embargo, ({}).toString.call(x).search(/String/)>0siempre regresa por cosas
fibrosas

1
function isClass(x,re){return ({}).toString.call(x).search(re)>0;}; isClass("hello",/String/) o isClass(3,/Number/)oisClass(null,/Null/)
no sincronizado el

2

Una solución simple sería:

var x = "hello"

if(x === x.toString()){
// it's a string 
}else{
// it isn't
}

1
Esto no comprueba si es una cadena. Se convierte en una cadena, muchas cosas tienen toString()función
Muhammad Umer

77
@MuhammadUmer Sí, lo convierte en una cadena pero luego comprueba la identidad con el valor original, que solo será verdadero si el valor original también es una cadena.
MrWhite

44
esto está mal: no puedes invocar ciegamente .toStringningún valor; pruebe si la x que se va a verificar es nula o indefinida, su excepción de lanzamiento de código
user5672998

1
La idea todavía es utilizable. x === La cadena (x) es segura y funciona.
Márton Sári

De Verdad? Esta solución me parece demasiado extraña, porque el toString()método puede ser anulado y puede generar una excepción (debido a alguna implementación específica), y su verificación no funcionará con seguridad. La idea principal es que no debe llamar a métodos que no están relacionados con lo que desea obtener. Ni siquiera estoy hablando de gastos generales innecesarios relacionados con el toStringmétodo. Votación a favor.
Rustem Zinnatullin

2

Un ayudante de 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

Además, si desea que sea recursivo (como Array que es un Objeto), puede usar instanceof .

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


2

Voy a tomar una ruta diferente al resto aquí, que intentará saber si una variable es un tipo específico o un miembro de un conjunto específico de tipos.
JS se basa en ducktyping; si algo grazna como una cadena, podemos y debemos usarlo como una cadena.

Es 7una cuerda? Entonces, ¿por qué /\d/.test(7)funciona?
Es {toString:()=>('hello there')}una cuerda? Entonces, ¿por qué ({toString:()=>('hello there')}) + '\ngeneral kenobi!'funciona?
Estas no son preguntas sobre si el trabajo anterior funciona, el punto es que lo hacen.

Así que hice una duckyString()función
A continuación, pruebo muchos casos no atendidos por otras respuestas. Para cada uno el código:

  • establece una variable similar a una cadena
  • ejecuta una operación de cadena idéntica y una cadena real para comparar salidas (lo que demuestra que pueden tratarse como cadenas)
  • convierte el tipo de cadena en una cadena real para mostrarle que duckyString()debe normalizar las entradas para el código que espera cadenas reales
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');

Esto está en la misma línea en !!xlugar de x===trueprobar algo si es como una matriz en lugar de necesitar una matriz real.
jQuery objetos; son matrices? No. ¿Son lo suficientemente buenos? Sí, puedes ejecutarlos a través de Array.prototypefunciones bien.
Es esta flexibilidad la que le da a JS su poder y las pruebas para cadenas específicamente hace que su código sea menos interoperables.

La salida de lo anterior es:

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"

Entonces, se trata de por qué quieres saber si algo es una cadena.
Si, como yo, llegaste aquí desde google y quisiste ver si algo era como una cadena , aquí hay una respuesta.
Ni siquiera es costoso a menos que esté trabajando con matrices de caracteres muy largas o profundamente anidadas.
Esto se debe a que es todo si las declaraciones, ninguna función llama como .toString().
Excepto si está tratando de ver si una matriz de caracteres con objetos que solo tienen toString()caracteres de varios bytes, en cuyo caso no hay otra forma de verificar, excepto hacer la cadena y contar los caracteres que componen los bytes, 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('');
    }
}

Se incluyen opciones para

  • preguntar qué método lo consideró string-y
  • excluir métodos de detección de cadenas (por ejemplo, si no le gusta .toString())

Aquí hay más pruebas porque soy un finalista:

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 los casos negativos parecen ser explicados
  • Esto debería ejecutarse en los navegadores> = IE8
  • Matrices de caracteres con múltiples bytes compatibles en navegadores con soporte de iterador de cadena

Salida:

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"

1

Solo para ampliar la respuesta de @ DRAX , haría esto:

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

También tendrá en cuenta nullsy undefinedtipos, y se encargará de los tipos que no son de cadena, como 0.


1

Esto es lo suficientemente bueno para mí.

ADVERTENCIA: Esta no es una solución perfecta. Ver el final de mi publicación.

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

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

Y puedes usar esto como a continuación.

//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"));

ADVERTENCIA: esto funciona incorrectamente en el caso:

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

isString(obj) //should be false, but true

-1

Puede usar esta función para determinar el tipo de cualquier cosa:

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

Para verificar si una variable es una cadena:

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

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


-2

No estoy seguro de si te refieres a saber si es un tipo stringindependientemente de su contenido, o si su contenido es un número o una cadena, independientemente de su tipo.

Entonces, para saber si su tipo es una cadena, eso ya ha sido respondido.
Pero para saber en función de su contenido si es una cadena o un número, usaría esto:

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

Y para algunos ejemplos:

isNumber(123);   //true
isNumber('123'); //true
isNumber('123a');//false
isNumber('');    //false

Creo que originalmente estaba preguntando cómo verificar el tipo, aunque no sabía cómo formular la pregunta en ese momento. (y probablemente solo haría esto /^\d+$/.test('123')para evitar las complejidades de los posibles problemas de análisis)
Olical
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.