Überprüfen Sie, ob eine Variable eine Zeichenfolge in JavaScript ist

1741

Wie kann ich feststellen, ob eine Variable eine Zeichenfolge oder etwas anderes in JavaScript ist?

Olical
quelle

Antworten:

1691

Sie können den typeofOperator verwenden:

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"

Beispiel von dieser Webseite . (Beispiel wurde jedoch leicht modifiziert).

Dies funktioniert bei mit erstellten Zeichenfolgen nicht wie erwartet new String(), wird jedoch selten verwendet und gegen [1] [2] empfohlen . In den anderen Antworten erfahren Sie, wie Sie damit umgehen können, wenn Sie dies wünschen.


  1. Im Google JavaScript Style Guide heißt es, niemals primitive Objekt-Wrapper zu verwenden .
  2. Douglas Crockford empfahl, primitive Objektverpackungen zu verwerfen .
Pablo Santa Cruz
quelle
45
@ Wolfy87 Bitte beachten Sie, dass in einigen Fällen der Typ stringValue möglicherweise "object" anstelle von "string" zurückgibt. Siehe Kommentare zu meiner Antwort.
DRAX
163
Meine bevorzugte Antwort. Das Argument dagegen ist, dass es für objektumschlossene Zeichenfolgen wie "fehlschlägt" new String('foo'), aber das spielt keine Rolle, da objektumschlossene Zeichenfolgen eine wertlose Funktion sind, die Sie nicht verwenden sollten. Der Google Style Guide verbietet sie , Douglas Crockford möchte, dass sie veraltet sind , und keine Bibliotheken verwenden sie. Stellen Sie sich vor, sie existieren nicht und verwenden Sie sie typeofohne Angst.
Mark Amery
2
@ DanielLe, weil er einen Ersatz vorgeschlagen hat, der einige Probleme behebt, nicht weil er grundsätzlich dagegen ist.
Vsevolod Golovanov
4
Wenn es Ihnen Kopfschmerzen bereitet, liegt dies in 99,99% der Fälle daran, dass Sie Ihren Code nicht richtig strukturiert haben. Das ist nicht NaNs Schuld daran, zu existieren und das zu tun, was es tut. Das sollten Sie zur Kenntnis nehmen, daraus lernen und berücksichtigen, wenn Sie das nächste Mal mit Code arbeiten, der es möglicherweise liefert.
Mike 'Pomax' Kamermans
1908

Das funktioniert bei mir:

if (typeof myVar === 'string' || myVar instanceof String)
// it's a string
else
// it's something else
DRAX
quelle
77
Tut "myVar instanceof String" etwas, das über "typeof myVar == 'string'" hinausgeht?
Svth
81
@svth Ich erinnerte mich. In JavaScript können Sie einen variablen Typ von Zeichenfolge oder einen Objekttyp haben, der eine Klasse von Zeichenfolgen ist (dasselbe - beide sind Zeichenfolgen - aber unterschiedlich definiert), weshalb dies doppelt überprüft wird.
DRAX
38
var somevar = neuer String ('somestring') console.log (typeof somevar) // Objekt
Danubian Sailor
82
-1, da die instanceofÜberprüfung hier sinnloses Rauschen ist, es sei denn, Sie befolgen einige sehr ungewöhnliche Codierungspraktiken, und diese Antwort erklärt nicht, was sie bewirkt oder warum Sie sie möglicherweise verwenden. Der einzige Grund, warum Sie es jemals brauchen würden, ist, wenn Sie objektumschlossene Zeichenfolgen verwenden, aber objektumschlossene Zeichenfolgen sind eine wertlose Funktion, die niemand verwendet, und Google und Crockford verurteilen beide als schlechte Praxis ( google-styleguide.googlecode.com/svn/). trunk /… , crockford.com/javascript/recommend.html ).
Mark Amery
79
Ich bin absolut anderer Meinung, dass das Schreiben von soliden Codes, die unwahrscheinliche Fälle korrekt behandeln, vermieden werden sollte. Überprüfen Sie beide typeofund instanceoffühlen Sie sich wie ein guter Rat, wenn Ihr Code von anderen aufgerufen werden kann. @ MarkAmerys Randfall ist postmessagewichtig, wenn Sie fragen "Was war ich gerade postmessaged?" - aber Sie würden erwarten, dass dies an der Schnittstelle behandelt wird und sich nicht verbreiten darf. An anderer Stelle scheint es richtig zu sein, mit nicht veralteten Codierungsmethoden umzugehen, selbst wenn einige JS-Ästhetiker sie ablehnen. Kommentieren Sie Ihren Code NIEMALS als akzeptierenden String, es sei denn, dies ist wirklich der Fall!
Dewi Morgan
157

Da mehr als 580 Personen für eine falsche Antwort gestimmt haben und mehr als 800 für eine funktionierende Antwort im Stil einer Schrotflinte gestimmt haben, hielt ich es für sinnvoll, meine Antwort in einer einfacheren Form zu wiederholen, die jeder verstehen kann.

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

Oder inline (ich habe ein UltiSnip-Setup dafür):

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

Zu Ihrer Information, die Antwort von Pablo Santa Cruz ist falsch, weil es so typeof new String("string")istobject

Die Antwort von DRAX ist genau und funktional und sollte die richtige sein (da Pablo Santa Cruz definitiv falsch ist und ich nicht gegen die Volksabstimmung argumentieren werde).

Diese Antwort ist jedoch auch definitiv richtig und tatsächlich die beste Antwort (außer vielleicht für den Vorschlag, lodash / Unterstrich zu verwenden ). Haftungsausschluss: Ich habe zur Codebasis von lodash 4 beigetragen.

Meine ursprüngliche Antwort (die offensichtlich über viele Köpfe flog) lautet wie folgt:

Ich habe dies von underscore.js transkodiert:

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

Das definiert isString, isNumber usw.


In Node.js kann dies als Modul implementiert werden:

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

[Bearbeiten]: Object.prototype.toString.call(x)Funktioniert auch zur Abgrenzung zwischen Funktionen und asynchronen Funktionen:

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

Orwellophil
quelle
11
Sie empfehlen underscore.js (aus welchem ​​Grund?), Verwenden es hier jedoch nicht. Außerdem verschmutzen Sie den globalen Namespace mit Funktionen. In node.js würden Sie ein Modul erstellen , das alle diese Funktionen haben würde (Sie können verwendet werden, global || windowanstatt windowaber das wäre ein schlechter Ansatz sein , ein Problem zu lösen , die Sie nicht an erster Stelle haben sollen).
Benjamin Gruenbaum
19
@BenjaminGruenbaum Ich habe nach der Antwort auf die Frage des OP gesucht und keine der Antworten gemocht. Also habe ich überprüft, was der Unterstrich bewirkt, und dachte, es sei geschickt genug, um ein wenig zu extrahieren und zu ändern (um zu vermeiden, dass die Unterstrichbibliothek geladen werden muss). Ich werde meinen Beitrag klären.
Orwellophile
2
@Orwellophile Cool, ich verstehe jetzt, Ihre ursprüngliche Antwort wurde so formuliert, als würden Sie vorschlagen, sich selbst zu unterstreichen. Persönlich würde ich nur prüfen myObject+"" === myObject, ob ein Objekt eine Zeichenfolge ist (oder noch besser, ich würde check überhaupt nicht in ein verhaltensgesteuertes Typsystem eingeben).
Benjamin Gruenbaum
18
@Orwellophile, wie ist das besser als die Antwort von DRAX?
Pacerier
3
JS unterstützt das Patchen von Affen, so dass es möglich ist, das toStringin der neu zu definieren Object.prototype. Ich würde also argumentieren, dass es toStringbestenfalls eine schlechte Praxis ist, sich darauf zu verlassen, den Typ eines Objekts zu überprüfen.
Andre Rodrigues
84

Ich empfehle die integrierten Funktionen von jQuery oder lodash / Underscore . Sie sind einfacher zu bedienen und leichter zu lesen.

Jede Funktion behandelt den erwähnten Fall DRAX ... das heißt, beide prüfen, ob (A) die Variable ein String-Literal oder (B) eine Instanz des String-Objekts ist. In beiden Fällen identifizieren diese Funktionen den Wert korrekt als Zeichenfolge.

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

Weitere Informationen finden Sie in der lodash-Dokumentation zu _.isString () .

Weitere Informationen finden Sie in der jQuery-Dokumentation zu $ ​​.type () .

ClearCloud8
quelle
97
Dies ist das Wesentliche an dem, was mit der JS-Community nicht stimmt. Die Überprüfung anhand des primitiven Typs ist ein Einzeiler und umfasst nur die Sprachkonstruktion (eine der grundlegenden). Sie empfehlen jedoch die Verwendung einer externen Bibliothek. Wenn jemand bereits eine dieser Bibliotheken verwendet, ist dies möglicherweise eine gute Idee, aber das Herunterladen nur für diesen Zweck, anstatt nur den Typ zu überprüfen, ist ein Overkill.
Rafał Wrzeszcz
5
Ich werde Rafal zustimmen. Ich sehe überall, dass es die "Lesbarkeit" verbessert, eine dieser externen Bibliotheken zu verwenden. Wenn Sie JavaScript kennen, ist dies einfacher zu lesen als eine externe Bibliothek, die Sie nicht verwendet haben. _.every()ist anfangs etwas verwirrend und etwas so Einfaches, wie _.isBoolean()es Entwickler in meiner Firma verwirrt hat. Ein Entwickler dachte fälschlicherweise, es wäre falsch, wenn der Wert ein Boolescher Wert und falsch wäre. Englisch ist für mich leichter zu lesen als Deutsch, weil ich kein Deutsch kann. Lernen Sie JavaScript und alles wird Sinn machen.
John Harding
20
@ RafałWrzeszcz Diese Bibliotheken sind ziemlich weit verbreitet und bieten viele nützliche (und getestete) Funktionen. Besonders lodash. Ich würde niemandem empfehlen, die Bibliothek nur für diese eine Lösung herunterzuladen ... aber ich würde jedem Javascript-Entwickler empfehlen, diese Bibliothek herunterzuladen und zu sehen, was ihm fehlt. ;)
ClearCloud8
13
Allen fehlt der Sinn einer Bibliothek wie Lodash: nicht Geschwindigkeit. Nicht "einfache Entwicklung". Der Grund für die Verwendung einer Bibliothek wie Lodash bietet "Abwehr" gegen Probleme, die Ihre js-App in die Luft jagen. Schwerwiegende Fehler treten auf, wenn Sie versuchen, Zeichenfolgenoperationen für ein Objekt auszuführen (oder umgekehrt), und Lodash bietet einen enormen Nutzen bei der Vermeidung dieser Fehler.
random_user_name
1
Denken Sie daran, dass viele Leute dies in einer Node- oder Node-ähnlichen Umgebung tun und nur sehr wenige Leute dort jQuery verwenden.
Matt Fletcher
35
function isString (obj) {
  return (Object.prototype.toString.call(obj) === '[object String]');
}

Das habe ich hier gesehen:

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

Leng
quelle
4
Ich denke, diese Lösung ist die robusteste, da sie Cross-Frame- / Cross-Window-Referenzszenarien behandelt, wie in der in der Antwort angegebenen URL angegeben.
ewh
1
Tolle Antwort, es sieht so aus, als ob Underscore.js auch diese Methode verwendet!
Daan
1
@ling Nur neugierig, warum setzen Sie Klammern Object.prototype.toString.call(obj) === '[object String]'?
StubbornShowaGuy
@Earlee Du meinst (x === y)hat eine bessere Lesbarkeit als x === y?
StubbornShowaGuy
@StubbornShowaGuy Meiner Meinung nach ja. Es geht auch um Konsistenz. Ich persönlich verwende immer Klammern, wenn ich einen Wert zurückgebe.
Aquarelle
28

Bester Weg:

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

Jedes von diesen wurde durch seine entsprechende Klassenfunktion wie "new Object ()" usw. konstruiert.

Ententypisierung: "Wenn es wie eine Ente aussieht, wie eine Ente läuft und wie eine Ente riecht - es muss ein Array sein" bedeutet, überprüfen Sie seine Eigenschaften.

Hoffe das hilft.

Bearbeiten; 12/05/2016

Denken Sie daran, dass Sie auch immer Kombinationen von Ansätzen verwenden können. Hier ist ein Beispiel für die Verwendung einer Inline-Karte von Aktionen mit typeof :

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

Hier ist ein realistischeres Beispiel für die Verwendung von Inline-Maps:

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

Diese Funktion würde [benutzerdefinierte] "Typumwandlung" - eher "Typ - / - Wertzuordnung" - verwenden, um herauszufinden, ob eine Variable tatsächlich "existiert". Jetzt können Sie das böse Haar zwischen null& aufteilen0 !

Oft interessiert man sich nicht einmal für seinen Typ . Eine andere Möglichkeit, das Tippen zu umgehen, besteht darin, Duck-Type-Sets zu kombinieren:

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

Beide Number.prototype und String.prototype haben eine .toString() method. Sie haben nur sichergestellt, dass das Zeichenfolgenäquivalent der Zahl identisch ist, und dann haben Sie sichergestellt, dass Sie es als httpFunktion an die Funktion übergeben haben Number. Mit anderen Worten, es war uns egal welchen Typ es sich handelte.

Hoffe das gibt dir mehr zum arbeiten :)

Cody
quelle
Sie würden eine andere Überprüfung für einfache alte Zahlen benötigen, da der Versuch, ihre Konstruktoreigenschaft zu übernehmen, fehlschlägt:
@torazaburo Hat in der Chrome-Konsole gerade gut funktioniert. Warum denkst du, dass es nicht funktioniert?
Mark Amery
2
@torazaburo Vielleicht möchten Sie mit den Behauptungen spielen ( (o.constructor === Number || s.constructor === Boolean)). Anekdotisch parseIntund NaNsind zerbrechliche, aber mächtige Werkzeuge. Denken Sie daran, dass Not-a-Number NICHT Not-a-Number ist und undefiniert definiert werden kann.
Cody
1
a.constructor === Array ist falsch und kann manchmal fehlschlagen. Verwenden Sie Array.isArray, siehe web.mit.edu/jwalden/www/isArray.html
axkibe
1
Einverstanden, das ist nicht ausfallsicher. Ein besserer Weg ist die Verwendung von Eigenschaftsprüfungen - DAS ist im Moment der einzig wirklich ausfallsichere Weg. Beispiel: if(thing.call) { 'its a function'; }oder if(thing.defineProperties) { 'its an object'; }. Danke für die Eingabe, Axkibe!
Cody
17

Ich kann ehrlich gesagt nicht verstehen, warum man typeofin diesem Fall nicht einfach verwenden würde :

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

Ja, es wird gegen objektumhüllte Zeichenfolgen (z. B. new String('foo')) fehlschlagen, aber diese werden allgemein als schlechte Praxis angesehen, und die meisten modernen Entwicklungswerkzeuge werden wahrscheinlich von ihrer Verwendung abraten. (Wenn Sie eine sehen, beheben Sie sie einfach!)

Der Object.prototype.toStringTrick ist etwas, das alle Front-End-Entwickler eines Tages in ihrer Karriere für schuldig befunden haben, aber lassen Sie sich nicht von seinem cleveren Glanz täuschen: Er wird kaputt gehen, sobald der Affen-Prototyp von einem Affen gepatcht wird:

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

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

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

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

Customcommander
quelle
15

Ich verwende gerne diese einfache Lösung:

var myString = "test";
if(myString.constructor === String)
{
     //It's a string
}
ScottyG
quelle
3
Wie unterscheidet sich das von Codys Antwort 4 Jahre später?
Jonathan H.
3
@Sheljohn Cody's Antwort ist großartig. Meine Antwort (vollständiger Text) ist kürzer und direkt auf den Punkt. Du hast gefragt ... :)
ScottyG
Als Funktion würde dies eine Möglichkeit erfordern, mit undefinedund umzugehen nullund dennoch die richtige Antwort für leere Zeichenfolgen (sowohl ''als auch new String('')) zu erhalten.
MikeBeaton
@ MikeBeaton Kein Problem : (mystring || false) && mystring.constructor === String. Ich habe false verwendet, falls es in einer Funktion verwendet wird, die einen Booleschen Wert zurückgeben muss.
Alans
13

Dies ist ein gutes Beispiel dafür, warum Leistung wichtig ist:

Etwas so Einfaches wie einen Test für einen String zu machen, kann teuer sein, wenn es nicht richtig gemacht wird.

Wenn ich beispielsweise eine Funktion schreiben wollte, um zu testen, ob etwas eine Zeichenfolge ist, kann ich dies auf zwei Arten tun:

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

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

Beide sind ziemlich einfach. Was könnte sich also möglicherweise auf die Leistung auswirken? Im Allgemeinen können Funktionsaufrufe teuer sein, insbesondere wenn Sie nicht wissen, was im Inneren passiert. Im ersten Beispiel gibt es einen Funktionsaufruf für die toString-Methode von Object. Im zweiten Beispiel gibt es keine Funktionsaufrufe, da typeof und instanceof Operatoren sind. Operatoren sind deutlich schneller als Funktionsaufrufe.

Wenn die Leistung getestet wird, ist Beispiel 1 79% langsamer als Beispiel 2!

Siehe die Tests: https://jsperf.com/isstringtype

Rob Brander
quelle
Der Testlink ist tot, aber ich glaube dir. Diese Art von Informationen ist sehr wichtig. IMHO sollte dies, wenn nicht die am besten bewertete Antwort, zumindest der am besten bewertete Kommentar zur aktuell führenden Antwort sein.
Coderer
typeof str === 'string' || str instanceof String(kann die Klammer fallen lassen, die ich in if (..)Fällen bevorzuge ); Unabhängig davon ist es klar und ausreichend, sowohl den primitiven als auch den Objekttyp in # 2 zu überprüfen. Diese Überprüfungen sollten sowieso "selten" sein.
user2864740
13
if (s && typeof s.valueOf() === "string") {
  // s is a string
}

Funktioniert sowohl für Zeichenfolgenliterale let s = 'blah'als auch für Objektzeichenfolgenlet s = new String('blah')

Radmacher
quelle
3
Beachtung! Dies wird bei leeren Zeichenfolgen fehlschlagen, da diese falsch sind.
Philipp Sumi
8

Entnommen aus 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
quelle
Wenn jemand die Quelle wissen möchte, ist es github.com/lodash/lodash/blob/master/isString.js
Ricardo Canelas
5

Ich denke, dass die @ customcommander-Lösung in 90% Ihrer Fälle ausreichen sollte:

typeof str === 'string'

Sollte dir recht geben (einfach da es normalerweise keinen Grund gibt zu haben new String('something') in Ihrem Code ).

Wenn Sie daran interessiert sind, die String Objekts (zum Beispiel erwarten Sie eine Variation von einem Drittanbieter), scheint die Verwendung von lodash als @ ClearCloud8 vorgeschlagen eine klare, einfache und elegante Lösung zu sein.

Ich würde jedoch empfehlen, mit Bibliotheken wie lodash aufgrund ihrer Größe vorsichtig zu sein. Anstatt zu tun

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

Was das ganze riesige Lodash-Objekt bringt, würde ich so etwas vorschlagen:

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

Und mit einfacher Bündelung sollte es Ihnen gut gehen (ich beziehe mich hier auf Client-Code).

Erez Cohen
quelle
warum === wann == ist genug
zavr
4

Wenn Sie in der Umgebung von node.js arbeiten, können Sie einfach die integrierte Funktion isString in utils verwenden.

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

Bearbeiten: Wie @Jehy erwähnt, ist dies seit v4 veraltet.

David
quelle
Gibt es einen Ersatz?
Anthony Kong
3
In den Dokumenten steht " typeof value === 'string'Stattdessen verwenden".
Herr Rogers
x = new String('x'); x.isString(x);gibt false zurück . Es gibt util.types.isStringObject()aber false für den x = 'x'Typ string. Zwei Dienstprogrammfunktionen, die absolut kein Dienstprogramm bieten ...
spinkus
4

Die folgende Methode überprüft, ob eine Variable eine Zeichenfolge ist ( einschließlich nicht vorhandener Variablen ).

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
quelle
3

Ich fand auch, dass dies auch gut funktioniert und es ist viel kürzer als die anderen Beispiele.

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

Durch Verketten mit leeren Anführungszeichen wird der Wert in eine Zeichenfolge umgewandelt. Wenn myVares sich bereits um eine Zeichenfolge handelt, ist die if-Anweisung erfolgreich.

Chris Dolphin
quelle
3
Das einzige Problem besteht darin, dass Sie eine Variable erzwingen, wenn Sie ihren Typ überprüfen möchten. Das scheint mir im Vergleich zu etwas teuer zu sein typeof.
Olical
1
Also ja, du hast recht. jsperf sagte, es sei ungefähr 20% langsamer als, typeofaber immer noch ziemlich viel schneller als toString. Wie auch immer, ich denke, ich mag nur die Syntax für das Erzwingen.
Chris Dolphin
4
Dies funktioniert nicht mit dem String-Typ. var s = new String('abc'); > s === s + '' > false
user5672998
1
Funktioniert nicht mit new Stringcus, das eine Art von erstellt object. w3schools.com/js/tryit.asp?filename=tryjs_string_object2
Chris Dolphin
Guter Gedanke, lässt aber den Randfall von objektumhüllten Strings weg.
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
quelle
Warum müssen Sie nach null oder undefiniert suchen, wenn x.constructor === String auch für null oder undefiniert false zurückgeben würde?
Jules Manson
1
@ JulesManson: Es würde einen Fehler auslösen, nicht produzieren false.
Ry-
3

Ich finde diese einfache Technik nützlich, um nach Zeichenfolgen zu suchen -

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

Die gleiche Technik funktioniert auch für 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

Und für 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

Gleiches gilt für Objekt -

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

NB, reguläre Ausdrücke, Arrays und Funktionen werden ebenfalls als Objekte betrachtet.

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)    

Die Suche nach Arrays ist jedoch etwas anders -

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

Diese Technik funktioniert jedoch nicht für Funktionen -

Function(x) === x // always false
Vielen Dank
quelle
var x = new String(x); String(x)===xgibt false zurück. ({}).toString.call(x).search(/String/)>0kehrt jedoch immer für strenge Dinge zurück
synchronisiert
1
function isClass(x,re){return ({}).toString.call(x).search(re)>0;}; isClass("hello",/String/) oder isClass(3,/Number/)oderisClass(null,/Null/)
unsynchronisiert
2

Eine einfache Lösung wäre:

var x = "hello"

if(x === x.toString()){
// it's a string 
}else{
// it isn't
}
Weder noch
quelle
1
Dies prüft nicht , ob es sich um eine Zeichenfolge handelt. Es macht eine Zeichenfolge, viele Dinge haben toString()Funktion
Muhammad Umer
7
@MuhammadUmer Ja, es konvertiert es in eine Zeichenfolge, prüft dann jedoch die Identität anhand des ursprünglichen Werts, der nur dann wahr ist, wenn der ursprüngliche Wert auch eine Zeichenfolge ist.
MrWhite
4
Das ist falsch: Sie können .toStringkeine Werte blind aufrufen . Versuchen Sie, wenn das zu überprüfende x null oder undefiniert ist, Ihre Code-
Auslöseausnahme
1
Die Idee ist noch verwendbar. x === String (x) ist sicher und funktioniert.
Márton Sári
"Ja wirklich?" Diese Lösung scheint mir zu seltsam, da die toString()Methode möglicherweise überschrieben wird und eine Ausnahme auslöst (aufgrund einer bestimmten Implementierung) und Ihre Prüfung nicht sicher funktioniert. Die Hauptidee ist, dass Sie keine Methoden aufrufen sollten, die nicht mit dem zusammenhängen, was Sie erhalten möchten. Ich spreche nicht einmal von unnötigem Overhead im Zusammenhang mit der toStringMethode. Downvoting.
Rustem Zinnatullin
2

Ein Typechecker-Helfer:

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

Verwendungszweck:

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

Auch wenn Sie möchten, dass es rekursiv ist (wie Array, das ein Objekt ist), können Sie es verwenden instanceof .

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

yaya
quelle
2

Ich werde hier einen anderen Weg als den Rest gehen und versuchen festzustellen, ob eine Variable ein bestimmter Typ oder ein Mitglied eines bestimmten Satzes von Typen ist.
JS basiert auf ducktyping; Wenn etwas wie eine Schnur quakt, können und sollten wir es wie eine Schnur verwenden.

Ist 7eine Zeichenfolge? Warum funktioniert /\d/.test(7)dann?
Ist {toString:()=>('hello there')}eine Zeichenfolge? Warum funktioniert ({toString:()=>('hello there')}) + '\ngeneral kenobi!'dann?
Dies sind keine Fragen zu sollten das oben Genannte funktionieren, der Punkt ist, dass sie es tun.

Also habe ich eine duckyString()Funktion erstellt. Im
Folgenden teste ich viele Fälle, die von anderen Antworten nicht berücksichtigt werden. Für jeden Code:

  • Setzt eine stringähnliche Variable
  • führt eine identische Zeichenfolgenoperation und eine echte Zeichenfolge aus, um die Ausgaben zu vergleichen (was beweist, dass sie wie Zeichenfolgen behandelt werden können)
  • konvertiert die Zeichenfolge in eine echte Zeichenfolge, um Ihnen duckyString()zu zeigen, wie Sie Eingaben für Code normalisieren können, der echte Zeichenfolgen erwartet
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');

Dies ist in der gleichen Weise wie !!xim Gegensatz zu x===trueund Testen, ob etwas Array- ähnlich ist, anstatt ein tatsächliches Array zu erfordern.
jQuery-Objekte; sind sie Arrays? Sind sie gut genug? Ja, Sie können sie problemlos durch Array.prototypeFunktionen ausführen .
Es ist diese Flexibilität, die JS seine Leistungsfähigkeit verleiht, und das Testen auf Zeichenfolgen macht Ihren Code weniger interoperabel.

Die Ausgabe der oben genannten ist:

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"

Es geht also darum, warum Sie wissen möchten, ob etwas eine Zeichenfolge ist.
Wenn Sie wie ich von Google hierher gekommen sind und sehen möchten, ob etwas stringartig ist , finden Sie hier eine Antwort.
Es ist nicht einmal teuer, wenn Sie nicht mit wirklich langen oder tief verschachtelten Char-Arrays arbeiten.
Dies liegt daran, dass es sich bei allen if-Anweisungen um keine Funktionsaufrufe handelt .toString().
Außer wenn Sie versuchen zu sehen, ob ein char-Array Objekte enthält, die nur aus toString()Zeichen oder Multibyte-Zeichen bestehen. In diesem Fall gibt es keine andere Möglichkeit, dies zu überprüfen, als die Zeichenfolge zu erstellen und die Zeichen zu zählen, aus denen die Bytes bestehen

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

Enthalten sind Optionen zu

  • Fragen Sie, welche Methode es als string-y erachtet
  • Methoden zur Zeichenfolgenerkennung ausschließen (z. B. wenn Sie nicht mögen .toString())

Hier sind weitere Tests, weil ich ein Vervollständiger bin:

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});
  • Alle negativen Fälle scheinen berücksichtigt zu sein
  • Dies sollte in Browsern> = IE8 ausgeführt werden
  • Char-Arrays mit mehreren Bytes werden in Browsern mit Unterstützung für Zeichenfolgeniteratoren unterstützt

Ausgabe:

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
quelle
1

Um die Antwort von @ DRAX zu erweitern , würde ich Folgendes tun:

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

Es berücksichtigt auch nulls und undefinedTypen und kümmert sich um Nicht-String-Typen, wie z 0.

ahmd0
quelle
1

Das ist gut genug für mich.

WARNUNG: Dies ist keine perfekte Lösung. Siehe den Ende meines Beitrags.

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

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

Und Sie können dies wie unten verwenden.

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

WARNUNG: Dies funktioniert nicht in dem Fall:

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

isString(obj) //should be false, but true
Tomozma
quelle
-1

Mit dieser Funktion können Sie den Typ von allem bestimmen:

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

So überprüfen Sie, ob eine Variable eine Zeichenfolge ist:

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
quelle
-2

Ich bin mir nicht sicher, ob Sie wissen wollen, ob es sich um einen Typ handelt, stringunabhängig von seinem Inhalt, oder ob es sich bei dem Inhalt um eine Zahl oder eine Zeichenfolge handelt, unabhängig von seinem Typ.

Um zu wissen, ob es sich bei dem Typ um eine Zeichenfolge handelt, wurde diese bereits beantwortet.
Aber um anhand des Inhalts zu wissen, ob es sich um eine Zeichenfolge oder eine Zahl handelt, würde ich Folgendes verwenden:

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

Und für einige Beispiele:

isNumber(123);   //true
isNumber('123'); //true
isNumber('123a');//false
isNumber('');    //false
Aryeh Beitz
quelle
Ich glaube, ich habe ursprünglich gefragt, wie ich den Typ überprüfen soll, obwohl ich damals noch nicht einmal wusste, wie ich die Frage formulieren soll. (und ich würde dies wahrscheinlich nur tun /^\d+$/.test('123'), um die
Komplikationen