Controlla se una variabile è una stringa in JavaScript


1743

Come posso determinare se una variabile è una stringa o qualcos'altro in JavaScript?

Risposte:


1692

È possibile utilizzare l' typeofoperatore:

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"

Esempio da questa pagina Web . (L'esempio è stato leggermente modificato).

Questo non funzionerà come previsto nel caso di stringhe create con new String(), ma raramente viene usato e raccomandato contro [1] [2] . Vedi le altre risposte su come gestirle, se lo desideri.


  1. La Guida di stile JavaScript di Google dice di non usare mai wrapper di oggetti primitivi .
  2. Douglas Crockford ha raccomandato di deprecare i wrapper di oggetti primitivi .

45
@ Wolfy87 Si informa che in alcuni casi typeof stringValue potrebbe restituire "object" anziché "string". Vedi i commenti sulla mia risposta.
DRAX,

163
La mia risposta preferita. L'argomento contrario è che "fallisce" per stringhe avvolte da oggetti come new String('foo'), ma questo non importa perché le stringhe avvolte da oggetti sono una caratteristica senza valore che non dovresti usare. La guida di stile di Google li proibisce , Douglas Crockford li vuole deprecati e nessuna biblioteca li usa. Fai finta che non esistano e usa typeofsenza paura.
Mark Amery,


2
@DanielLe, perché ha proposto un sostituto che risolve alcuni problemi, non perché è contrario in linea di principio.
Vsevolod Golovanov,

4
Se ti provoca mal di testa, il 99,99% delle volte è perché non hai strutturato correttamente il codice. Non è colpa di NaN per esistere e fare ciò che fa, è qualcosa di cui dovresti prendere nota, imparare e tenere a mente la prossima volta che lavori con il codice che potrebbe produrlo.
Mike 'Pomax' Kamermans,

1910

Questo è ciò che funziona per me:

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

77
"MyVar instanceof String" fa qualcosa sopra e oltre "typeof myVar == 'string'"?
svth

81
@svth mi sono ricordato. In JavaScript puoi avere un tipo variabile di stringa o un tipo di oggetto che è la classe di String (stessa cosa - entrambe sono stringhe - ma definite in modo diverso) ecco perché viene verificato due volte.
DRAX,

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

82
-1 perché il instanceofcontrollo qui è un rumore inutile a meno che tu non stia seguendo alcune pratiche di codifica molto insolite , e questa risposta non fa nulla per spiegare cosa fa o perché potresti usarlo. L'unico motivo per cui ne avresti mai bisogno è se usi stringhe avvolte da oggetti, ma le stringhe avvolte da oggetti sono una funzione inutile che nessuno usa e Google e Crockford condannano entrambi come cattiva pratica ( google-styleguide.googlecode.com/svn/ trunk /… , crockford.com/javascript/recommend.html ).
Mark Amery,

79
Non sono assolutamente d'accordo sul fatto che scrivere codice solido che gestisca correttamente casi improbabili sia qualcosa da evitare. Controllando entrambi typeofe instanceofsembra un buon consiglio se il tuo codice può essere chiamato da altri. @ Il postmessagecaso limite di MarkAmery è importante se stai chiedendo "cosa stavo solo postmessaged?" - ma ti aspetteresti che venga gestito all'interfaccia e non ti sia permesso di propagarsi. Altrove, sembra corretto gestire metodi di codifica non deprecati anche se alcuni esteti JS non li approvano. Non commentare MAI il tuo codice come accettante String, a meno che non lo faccia davvero!
Dewi Morgan,

157

Dato che 580+ persone hanno votato per una risposta errata e 800+ hanno votato per una risposta funzionante ma in stile fucile, ho pensato che valesse la pena rifare la mia risposta in una forma più semplice che tutti possano capire.

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

Oppure, in linea (ho una configurazione UltiSnip per questo):

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

Cordiali saluti, la risposta di Pablo Santa Cruz è sbagliata, perché lo typeof new String("string")èobject

La risposta di DRAX è accurata e funzionale e dovrebbe essere la risposta corretta (dal momento che Pablo Santa Cruz è decisamente errato e non discuterò contro il voto popolare).

Tuttavia, questa risposta è anche sicuramente corretta, e in realtà la risposta migliore (tranne, forse, per il suggerimento di usare lodash / trattino basso ). disclaimer: ho contribuito alla base di codice lodash 4.

La mia risposta originale (che ovviamente ha sorvolato molte teste) segue:

Ho transcodificato questo da underscore.js:

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

Ciò definirà isString, isNumber, ecc.


In Node.js, questo può essere implementato come un modulo:

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

[modifica]: Object.prototype.toString.call(x)funziona anche per delineare tra funzioni e funzioni asincrone:

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
Raccomandi underscore.js (per quale strana ragione?) Ma non lo usi qui. Inoltre inquini lo spazio dei nomi globale con funzioni. In node.js avresti creato un modulo che avrebbe tutte queste funzioni ( puoi usare global || windowinvece di windowma sarebbe un cattivo approccio per risolvere un problema che non dovresti avere in primo luogo).
Benjamin Gruenbaum,

19
@BenjaminGruenbaum Sono venuto a cercare la risposta alla domanda del PO, e non mi è piaciuta nessuna delle risposte. Quindi ho verificato cosa ha fatto il carattere di sottolineatura e ho pensato che fosse abbastanza ingegnoso da estrarre e modificare un po '(per evitare di dover caricare la libreria del carattere di sottolineatura). Chiarirò il mio post.
Orwellophile,

2
@Orwellophile Cool, ora capisco, la tua risposta originale è stata formulata come se tu stessi suggerendo di sottolinearlo. Personalmente vorrei solo controllare myObject+"" === myObjectse un oggetto è una stringa (o meglio, non scriverei il check in un sistema di tipi basato sul comportamento in primo luogo).
Benjamin Gruenbaum,

18
@Orwellophile, in che modo è meglio della risposta di DRAX?
Pacerier,

3
JS supporta il patching delle scimmie, quindi è possibile ridefinire toStringil file Object.prototype. Quindi, direi che fare affidamento sul toStringcontrollo del tipo di un oggetto è, nella migliore delle ipotesi, una cattiva pratica.
Andre Rodrigues,

84

Consiglio di utilizzare le funzioni integrate di jQuery o lodash / Underscore . Sono più semplici da usare e più facili da leggere.

Entrambe le funzioni gestiranno il caso DRAX menzionato ... cioè, entrambi controlleranno se (A) la variabile è una stringa letterale o (B) è un'istanza dell'oggetto String. In entrambi i casi, queste funzioni identificano correttamente il valore come una stringa.

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

Vedere la documentazione di lodash per _.isString () per maggiori dettagli.

Vedere la documentazione di jQuery per $ .type () per maggiori dettagli.


97
Questo è l'essenziale di ciò che non va nella comunità JS: il controllo del tipo primitivo è un singolo e implica solo la costruzione del linguaggio (uno dei fondamentali), ma si consiglia di utilizzare una libreria esterna. Se qualcuno utilizza già una di queste librerie, potrebbe essere una buona idea, ma scaricarle solo per quello invece di controllare semplicemente il tipo è eccessivo.
Rafał Wrzeszcz,

5
Sono d'accordo con Rafal. Vedo dappertutto che migliora la "leggibilità" per usare una di queste librerie esterne. Se conosci JavaScript, è più facile da leggere rispetto ad alcune librerie esterne che non hai usato. _.every()è un po 'confuso da usare all'inizio, e qualcosa di così semplice come _.isBoolean()ha confuso gli sviluppatori della mia compagnia. Uno sviluppatore ha erroneamente pensato che sarebbe falso se il valore fosse un valore booleano ed era falso. L'inglese è più facile da leggere del tedesco per me, perché non conosco il tedesco. Impara JavaScript e tutto avrà un senso.
John Harding,

20
@ RafałWrzeszcz Queste librerie sono abbastanza ampiamente utilizzate e offrono funzionalità molto utili (e testate). Soprattutto lodash. Non consiglierei a qualcuno di scaricare la libreria da utilizzare solo per questa soluzione .... ma consiglierei a tutti gli sviluppatori javascript di scaricare questa libreria e vedere cosa si stanno perdendo. ;)
ClearCloud8

13
A tutti voi manca il punto di una biblioteca come Lodash: non la velocità. Non "facilità di sviluppo". Il motivo per usare una libreria come Lodash fornisce "difesa" contro i problemi che faranno esplodere la tua app js. Si verificano errori irreversibili quando si tenta di eseguire operazioni su stringa su un oggetto (o viceversa) e Lodash fornisce un valore straordinario nella prevenzione di tali errori.
random_user_name

1
Tieni presente che molte persone lo faranno in un ambiente simile a un nodo o nodo e che pochissime persone useranno jQuery lì.
Matt Fletcher,

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

L'ho visto qui:

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


4
Penso che questa soluzione sia la più solida poiché gestisce scenari di riferimento cross-frame / cross-window come indicato nell'URL fornito nella risposta.
ewh,

1
Ottima risposta, sembra che Underscore.js usi anche questo metodo!
Daan,

1
@ling Solo curioso, perché metti tra parentesi Object.prototype.toString.call(obj) === '[object String]'?
Testardo

@Earlee Vuoi dire che (x === y)ha una migliore leggibilità di x === y?
Testardo Mostra

@StubbornShowaGuy Secondo me, sì. Riguarda anche la coerenza. Personalmente utilizzo sempre le parentesi quando restituisco un valore.
Aquarelle,

28

Miglior modo:

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

Ognuno di questi è stato costruito dalla sua funzione di classe appropriata, come "new Object ()" ecc.

Inoltre, Duck-Typing: "Se sembra un'anatra, cammina come un'anatra e profuma di anatra - deve essere una matrice" Significato, controlla le sue proprietà.

Spero che sia di aiuto.

Modificare; 2016/12/05

Ricorda, puoi sempre usare anche combinazioni di approcci. Ecco un esempio dell'uso di una mappa incorporata di azioni con typeof :

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

Ecco un esempio più "reale" dell'uso delle mappe in linea:

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

Questa funzione userebbe [custom] "type-casting" - piuttosto, "type - / - value-mapping" - per capire se una variabile "esiste". Ora puoi dividere quei capelli cattivi tra null& 0!

Molte volte non ti interessa nemmeno del suo tipo . Un altro modo per aggirare la digitazione è la combinazione di set Duck-Type:

this.id = "998";  // use a number or a string-equivalent
function get(id) {
    if (!id || !id.toString) return;
    if (id.toString() === this.id.toString()) http( id || +this.id );
    // if (+id === +this.id) ...;
}

Entrambi Number.prototype e String.prototype hanno a .toString() method. Hai appena fatto in modo che l'equivalente in stringa del numero fosse lo stesso e poi ti sei assicurato di averlo passato alla httpfunzione come a Number. In altre parole, non abbiamo nemmeno cura ciò che il suo tipo era.

Spero che ti dia di più per lavorare :)


Avresti bisogno di qualche altro controllo per i vecchi numeri semplici, poiché il tentativo di prendere la loro proprietà del costruttore fallirà:

@torazaburo Ha funzionato bene per me proprio ora nella console di Chrome. Cosa ti fa pensare che non funzionerà?
Mark Amery,

2
@torazaburo Potresti voler giocare con le asserzioni ( (o.constructor === Number || s.constructor === Boolean)). Aneddoticamente, parseInte NaNsono strumenti fragili ma potenti. Ricorda, Not-a-Number NON NOT-a-Number e undefined può essere definito.
Cody,

1
a.constructor === L'array è sbagliato e a volte può fallire, usa Array.isArray vedi web.mit.edu/jwalden/www/isArray.html
axkibe

1
D'accordo, questo non è sicuro. Un modo migliore è quello di utilizzare i controlli di proprietà - QUESTO è l'unico modo veramente sicuro per il momento. Esempio: if(thing.call) { 'its a function'; }o if(thing.defineProperties) { 'its an object'; }. Grazie per l'input, axkibe!
Cody,

17

Onestamente non riesco a capire perché non si debba semplicemente usare typeofin questo caso:

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

Sì, fallirà contro le stringhe avvolte da oggetti (ad es. new String('foo')), Ma queste sono ampiamente considerate come una cattiva pratica e la maggior parte degli strumenti di sviluppo moderni può scoraggiare il loro uso. (Se ne vedi uno, risolvilo e basta!)

Il Object.prototype.toStringtrucco è qualcosa che tutti gli sviluppatori front-end sono stati giudicati colpevoli di fare un giorno nella loro carriera, ma non lasciarti ingannare dalla sua raffinatezza intelligente: si romperà non appena qualcosa scimmia rattoppierà il prototipo dell'Oggetto:

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

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

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

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


15

Mi piace usare questa semplice soluzione:

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

3
In che modo differisce dalla risposta di Cody, 4 anni dopo?
Jonathan H,

3
La risposta di @Sheljohn Cody è fantastica. La mia risposta (testo completo) è più breve e diretta al punto. Hai chiesto ... :)
ScottyG,

Come funzione, ciò avrebbe bisogno di un modo per gestire undefinede null, e ottenere comunque la risposta giusta per stringhe vuote (sia ''e che new String('')).
MikeBeaton,

@MikeBeaton Nessun problema: (mystring || false) && mystring.constructor === String. Ho usato false nel caso in cui sia usato in una funzione che deve restituire un valore booleano.
Alani

13

Questo è un ottimo esempio del perché le prestazioni contano:

Fare qualcosa di semplice come un test per una stringa può essere costoso se non eseguito correttamente.

Ad esempio, se volessi scrivere una funzione per verificare se qualcosa è una stringa, potrei farlo in due modi:

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

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

Entrambi sono piuttosto semplici, quindi cosa potrebbe avere un impatto sulle prestazioni? In generale, le chiamate di funzione possono essere costose, soprattutto se non sai cosa sta succedendo all'interno. Nel primo esempio, c'è una chiamata di funzione al metodo toString di Object. Nel secondo esempio, non ci sono chiamate di funzione, poiché typeof e instanceof sono operatori. Gli operatori sono significativamente più veloci delle chiamate di funzione.

Quando le prestazioni vengono testate, l'esempio 1 è più lento del 79% rispetto all'esempio 2!

Vedi i test: https://jsperf.com/isstringtype


Il link del test è morto, ma ti credo. Questo tipo di informazioni è estremamente importante. IMHO questa dovrebbe essere, se non la risposta più votata, almeno il commento più votato sulla risposta iniziale corrente.
Coderer

typeof str === 'string' || str instanceof String(può rilasciare la parentesi che preferisco nei if (..)casi); a prescindere, controllare sia il tipo primitivo che quello dell'oggetto in # 2 è chiaro e sufficiente. Questi controlli dovrebbero comunque essere "rari".
user2864740

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

Funziona sia con valori letterali di stringa sia con stringhe let s = 'blah'di oggettilet s = new String('blah')


3
Attenzione! Questo fallirà su stringhe vuote, poiché quelle sono false.
Philipp Sumi,

8

Tratto da 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

Se qualcuno vuole conoscere la fonte, è github.com/lodash/lodash/blob/master/isString.js
Ricardo Canelas,

5

Penso che la soluzione @customcommander dovrebbe essere sufficiente nel 90% dei tuoi casi:

typeof str === 'string'

Dovrebbe servirti nel modo giusto (semplicemente perché normalmente non c'è motivo di avere new String('something')nel tuo codice).

Se sei interessato a gestire il String oggetto (ad esempio ti aspetti qualche var da una terza parte), usare lodash come suggerito da @ ClearCloud8 sembra una soluzione chiara, semplice ed elegante.

Vorrei tuttavia suggerire di essere cauti con le biblioteche come lodash a causa delle loro dimensioni. Invece di farlo

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

Il che porta l'intero enorme oggetto lodash, suggerirei qualcosa del tipo:

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

E con un semplice raggruppamento dovresti andare bene (mi riferisco qui al codice client).


perché === quando == è sufficiente
zavr

4

Se lavori nell'ambiente node.js, puoi semplicemente utilizzare la funzione integrata isString in utils.

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

Modifica: come accennato da @Jehy, questo è obsoleto dalla v4.


C'è qualche rimpiazzo?
Anthony Kong,

3
I documenti dicono "Usa typeof value === 'string'invece".
Mr Rogers,

x = new String('x'); x.isString(x);restituisce false . C'è util.types.isStringObject()ma restituisce false per il x = 'x'tipo stringa. Due funzioni di utilità che non forniscono assolutamente alcuna utilità ...
spinkus

4

Il seguente metodo verificherà se una variabile è una stringa ( comprese le variabili che non esistono ).

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

Ho anche scoperto che anche questo funziona bene, ed è molto più breve degli altri esempi.

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

Concatenando virgolette vuote trasforma il valore in una stringa. Se myVarè già una stringa, l'istruzione if ha esito positivo.


3
L'unico problema è che stai forzando una variabile quando vuoi controllarne il tipo. Mi sembra un po 'caro rispetto a typeof.
Olical,

1
Quindi sì, hai ragione. jsperf ha detto che era circa il 20% più lento di typeofma ancora un po 'più veloce di toString. Ad ogni modo, immagino che mi piace solo la sintassi per il coercing.
Chris Dolphin,

4
questo non funziona con il tipo String; var s = new String('abc'); > s === s + '' > false
user5672998

1
Non funziona con new Stringcus che crea un tipo di object. w3schools.com/js/tryit.asp?filename=tryjs_string_object2
Chris Dolphin

Buona idea, ma lascia fuori il caso limite di stringhe avvolte da oggetti.
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))

Perché è necessario controllare null o undefined se x.constructor === String restituisce anche false per null o undefined?
Jules Manson,

1
@JulesManson: genererebbe un errore, non produrrebbe false.
Ry-

3

Trovo questa semplice tecnica utile per il controllo del tipo di 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 stessa tecnica funziona anche per 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 per 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 stesso per l' oggetto -

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

NB, regexps, array e funzioni sono considerati anche oggetti.

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)    

Ma controllare l' array è un po 'diverso -

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

Questa tecnica non non funziona per le funzioni tuttavia -

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

var x = new String(x); String(x)===xrestituisce false. tuttavia ({}).toString.call(x).search(/String/)>0ritorna sempre per cose
difficili

1
function isClass(x,re){return ({}).toString.call(x).search(re)>0;}; isClass("hello",/String/) oppure isClass(3,/Number/)oppureisClass(null,/Null/)
non sincronizzato il

2

Una soluzione semplice sarebbe:

var x = "hello"

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

1
questo non controlla se è una stringa. Si trasforma in una stringa, molte cose hanno una toString()funzione
Muhammad Umer,

7
@MuhammadUmer Sì, lo converte in una stringa ma quindi controlla l'identità rispetto al valore originale, che sarà vero solo se il valore originale è anche una stringa.
MrWhite,

4
questo è sbagliato: non puoi chiamare ciecamente .toStringalcun valore; prova se la x da controllare è nulla o non definita, il tuo codice genera un'eccezione
user5672998

1
L'idea è ancora utilizzabile. x === String (x) è sicuro e funziona.
Márton Sári

Veramente? Questa soluzione mi sembra troppo strana, perché il toString()metodo potrebbe essere ignorato e potrebbe generare un'eccezione (a causa di un'implementazione specifica) e il tuo controllo non funzionerà di sicuro. L'idea principale è che non dovresti chiamare metodi che non sono correlati a ciò che vuoi ottenere. Non sto nemmeno parlando di spese generali non necessarie legate al toStringmetodo. Downvoting.
Rustem Zinnatullin,

2

Un aiutante Typechecker:

function isFromType(variable, type){
  if (typeof type == 'string') res = (typeof variable == type.toLowerCase())
  else res = (variable.constructor == type)
  return res
}

utilizzo:

isFromType('cs', 'string') //true
isFromType('cs', String) //true
isFromType(['cs'], Array) //true
isFromType(['cs'], 'object') //false

Inoltre, se si desidera che sia ricorsivo (come una matrice che è un oggetto), è possibile utilizzare instanceof.

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


2

Ho intenzione di seguire una strada diversa rispetto al resto qui, che prova a dire se una variabile è un tipo specifico o un membro di un insieme specifico di tipi.
JS è costruito su ducktyping; se qualcosa cade come una stringa, possiamo e dovremmo usarla come una stringa.

È 7una stringa? Allora perché /\d/.test(7)funziona?
È {toString:()=>('hello there')}una stringa? Allora perché ({toString:()=>('hello there')}) + '\ngeneral kenobi!'funziona?
Queste non sono domande su dovrebbe il lavoro di cui sopra, il punto è che fanno.

Quindi ho fatto una duckyString()funzione
Di seguito ho testato molti casi non soddisfatti da altre risposte. Per ciascuno il codice:

  • imposta una variabile simile a una stringa
  • esegue un'operazione di stringa identica su di essa e una stringa reale per confrontare gli output (dimostrando che possono essere trattati come stringhe)
  • converte il tipo di stringa in una stringa reale per mostrare duckyString()all'utente di normalizzare gli input per il codice che prevede stringhe reali
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');

Questo è nella stessa vena di !!xopposto x===truee test se qualcosa è simile a un array invece di richiedere un array reale.
oggetti jQuery; sono array? No. Sono abbastanza bravi? Sì, puoi eseguirli attraverso le Array.prototypefunzioni bene.
È questa flessibilità che dà a JS la sua potenza e il test per stringhe rende specificamente il tuo codice meno interoperabile.

L'output di quanto sopra è:

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"

Quindi, tutto dipende dal motivo per cui vuoi sapere se qualcosa è una stringa.
Se, come me, sei arrivato qui da Google e volevi vedere se qualcosa era simile a una stringa , ecco una risposta.
Non è nemmeno costoso a meno che non lavori con array di caratteri molto lunghi o profondamente annidati.
Questo perché è tutto se le istruzioni, nessuna funzione chiama come .toString().
Tranne se stai provando a vedere se un array di caratteri con oggetti che hanno solo toString()caratteri multi-byte o, nel qual caso non c'è altro modo di controllare se non per creare la stringa e contare i caratteri che compongono i byte, rispettivamente

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

Sono incluse opzioni per

  • chiedi quale metodo lo ha considerato string-y
  • escludere metodi di rilevamento delle stringhe (ad es. se non ti piace .toString())

Ecco altri test perché sono un 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});
  • Tutti i casi negativi sembrano essere giustificati
  • Questo dovrebbe essere eseguito su browser> = IE8
  • Array di caratteri con più byte supportati nei browser con supporto iteratore di stringhe

Produzione:

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 per espandere la risposta di @ DRAX , farei questo:

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

Terrà conto anche di tipi nulle undefinedtipi e si occuperà di tipi non stringa, come ad esempio 0.


1

Questo è abbastanza buono per me.

ATTENZIONE: questa non è una soluzione perfetta. Vedi il fondo del mio 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 puoi usarlo come di seguito.

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

ATTENZIONE: questo funziona in modo errato nel caso:

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

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

-1

Puoi usare questa funzione per determinare il tipo di qualsiasi cosa:

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

Per verificare se una variabile è una stringa:

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

Non sono sicuro se intendi sapere se è un tipo stringindipendentemente dal suo contenuto o se il suo contenuto è un numero o una stringa, indipendentemente dal suo tipo.

Quindi per sapere se il suo tipo è una stringa, è già stata data una risposta.
Ma per sapere in base al suo contenuto se è una stringa o un numero, vorrei usare questo:

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

E per alcuni esempi:

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

Penso che inizialmente stavo chiedendo come controllare il tipo, anche se non sapevo nemmeno come fare la domanda allora. (e probabilmente lo farei semplicemente /^\d+$/.test('123')per evitare la complessità di potenziali problemi di analisi)
Olical
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.