Jak mogę określić, czy zmienna jest ciągiem lub czymś innym w JavaScript?

2179
Olical 30 październik 2010, 18:36

23 odpowiedzi

Najlepsza odpowiedź

Możesz użyć operatora typeof:

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"

Przykład z Ta strona. (Przykład był nieznacznie zmodyfikowany).

To nie będzie działać zgodnie z oczekiwaniami w przypadku ciągów utworzonych za pomocą new String(), ale rzadko jest rzadko stosowane i zalecane przed [1] [2] . Zobacz inne odpowiedzi na to, jak sobie z tym poradzić, jeśli tak pragniesz.


  1. Przewodnik po stylu JavaScript Google mówi, aby nigdy nie używać prymitywnych opakowań obiektowych .
  2. Douglas Crockford Zalecany, aby przebity prymitywne opakowania obiektowe.
1922
WD40 6 listopad 2018, 08:14

To właśnie działa dla mnie:

if (typeof myVar === 'string' || myVar instanceof String)
// it's a string
else
// it's something else
2094
Mark Amery 16 luty 2017, 19:25

Od 580+ osób głosowało na niepoprawną odpowiedź, a 800+ głosowało na pracę, ale odpowiedź w stylu strzelby, pomyślałem, że warto ponieść moją odpowiedź w prostszej formie, którą każdy może zrozumieć.

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

Lub inline (mam dla tego konfigurację Ultisnipa):

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

FYI, odpowiedź Pablo Santa Cruz jest nie tak, ponieważ typeof new String("string") object

Odpowiedź Drax jest dokładna i funkcjonalna, a powinna być prawidłową odpowiedzią (ponieważ Pablo Santa Cruz jest zdecydowanie niepoprawnie, a ja nie będę kłócić się przeciwko popularnym głosowaniu).

Jednak ta odpowiedź jest również zdecydowanie poprawna, a właściwie najlepsza odpowiedź (z wyjątkiem, być może, do sugestii korzystania Lodash / podkreślenia). Zrzeczenie się: przyczyniłem się do Lodash 4 CodeBase.

Moja pierwotna odpowiedź (która oczywiście poleciała prosto nad wieloma głowami) następuje:

Transcoded to od underscore.js:

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

To zdefiniuje wyświetlanie, isnumber itp.


W NODE.JS można to zaimplementować jako moduł:

module.exports = [
  'Arguments', 
  'Function', 
  'String', 
  'Number', 
  'Date', 
  'RegExp'
].reduce( (obj, name) => {
  obj[ 'is' + name ] = x => toString.call(x) == '[object ' + name + ']';
  return obj;
}, {});
187
agm1984 26 maj 2020, 20:51

Polecam użycie wbudowanych funkcji z jQuery lub Lodash / podkreślenia . Są prostsze do użycia i łatwiej czytać.

Każda funkcja obsłuży wspomniana obudowa Drax ... czyli, one zarówno , czy (a) zmienna jest literą ciągową lub (b) jest instancją obiektu ciągów. W obu przypadkach funkcje te poprawnie określają wartość jako ciąg.

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

Zobacz Dokumentacja Lodash dla _.isstring () Więcej informacji.

Zobacz Dokumentacja jQuery dla $ .type () Więcej informacji.

86
ClearCloud8 22 wrzesień 2015, 15:12
function isString (obj) {
  return (Object.prototype.toString.call(obj) === '[object String]');
}

Widziałem to tutaj:

http://perfectionkillills.com/instanceof-considered-harmful-or-how-to-write-a-Obust-isarray/

36
Balthazar 8 lipiec 2016, 16:14

Nie mogę szczerze zobaczyć, dlaczego po prostu nie użyjeby typeof w tym przypadku:

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

Tak, nie powiedzie się przed zwinięciem obiektów (np. new String('foo')), ale są one powszechnie uważane za złej praktyki, a większość nowoczesnych narzędzi rozwojowych prawdopodobnie zniechęcają do ich użycia. (jeśli go zobaczysz, po prostu napraw go!)

Sztuczka Object.prototype.toString jest czymś, co stwierdzono, że wszyscy deweloperzy frontowe zostały uznane winne z robienia jednego dnia w ich karierze, ale nie pozwól, żeby cię oszukać przez swojego polskiego sprytnego: przełamuje się jak tylko coś małpy-łata prototyp obiektu:

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

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

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

console.log(isString('foo'));
26
customcommander 18 styczeń 2019, 23:22

Prostym rozwiązaniem byłoby:

var x = "hello"

if(x === x.toString()){
// it's a string 
}else{
// it isn't
}
3
Noris 15 sierpień 2019, 09:15

Idę tu inną drogę do reszty, który próbuje powiedzieć, czy zmienna jest specyficzna lub członek określonego zestawu typów.
JS jest zbudowany na kaczce; Jeśli coś rzuca się jak łańcuch, możemy i powinien użyć go jak ciąg.

Czy 7 sznur? Więc dlaczego /\d/.test(7) działa?
Jest {toString:()=>('hello there')} sznur? Więc dlaczego ({toString:()=>('hello there')}) + '\ngeneral kenobi!' działa?
Nie są one pytaniami o powinny Powyższe prace, co oznacza.

Zrobiłem więc duckyString() Funkcja
Poniżej przetestuję wiele przypadków, które nie są zaspokajane przez inne odpowiedzi. Dla każdego kodu:

  • Ustawia zmienną podobną do strun
  • Uruchamia identyczną obsługę ciągów i prawdziwy ciąg do porównania wyjść (udowodnienie, że mogą być traktowane jak ciągłe)
  • Konwertuje ciąg znaków do rzeczywistego, aby pokazać Ci duckyString(), aby normalizować wejścia dla kodu, które oczekuje rzeczywistych ciągów
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');

Jest to w tej samej żyła, co !!x, a nie x===true i testowanie, jeśli coś jest array- jak zamiast wymagać rzeczywistej tablicy.
Obiekty jQuery; czy są tablicami? Nie. Czy są wystarczająco dobrzy? Tak, możesz je uruchomić przez Array.prototype funkcje w porządku.
Jest to elastyczność, która daje JS jego mocy i testowanie dla ciągi sprawia, że kod jest mniej interoperacyjny.

Wynik powyższego to:

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"

Więc chodzi o Dlaczego chcesz wiedzieć, czy coś jest sznurkiem.
Jeśli, podobnie jak ja dotarłeś tutaj z Google i chciałeś zobaczyć, czy coś było jak , oto odpowiedź.
Nie jest nawet drogi, chyba że pracujesz z naprawdę długo lub głęboko zagnieżdżonymi tablicami.
Dzieje się tak dlatego, że to wszystko, jeśli wyciągi, bez funkcji, takich jak .toString().
chyba że próbujesz zobaczyć, czy tablica znaków z obiektami, które mają tylko znaki toString(), w którym to przypadku nie ma innego sposobu sprawdzenia, z wyjątkiem ciągów, i liczby znaki bajtów makijaż, odpowiednio

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

Zawarte są opcje

  • Zapytaj, która metoda uznaje się za string-y
  • wykluczyć metody wykrywania string (np. Jeśli nie lubisz .toString())

Oto więcej testów, ponieważ jestem kompletem:

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});
  • Wszystkie negatywne przypadki wydają się być rozliczane
  • To powinno działać na przeglądarkach> = IE8
  • Char Mayra z wieloma bajkami obsługiwanymi na przeglądarkach z obsługą String Iterator

Wynik:

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"
3
Hashbrown 1 luty 2020, 06:02

Możesz użyć tej funkcji, aby określić typ czegokolwiek:

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

Aby sprawdzić, czy zmienna jest ciągiem:

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.

3
Pato 3 lipiec 2020, 13:10

To mi wystarczy.

OSTRZEŻENIE: To nie jest idealne rozwiązanie. Zobacz na dole mojego posta.

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

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

I możesz użyć tego jak poniżej.

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

OSTRZEŻENIE: Działa to nieprawidłowo w przypadku:

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

isString(obj) //should be false, but true
2
Tomozma 24 październik 2018, 04:14

Melakier:

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

Stosowanie:

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

Również jeśli chcesz, aby był rekurencyjny (jak tablica, która jest obiektem), możesz użyć instanceof.

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

2
yaya 1 październik 2019, 12:33

Wystarczy rozwinąć o @ Drax's Odpowiedź, zrobiłbym to:

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

Będzie również uwzględnić typy null s

1
Community 23 maj 2017, 10:31

Nie jestem pewien, czy masz na myśli wiedząc, czy jest to typ string niezależnie od jego zawartości, czy też to zawartość jest liczbą lub ciągiem, niezależnie od tego typu.

Aby dowiedzieć się więc, czy jego typ jest ciągiem, który już został odpowiedział.
.. Ale wiedzieć na podstawie jego zawartości, jeśli jego ciąg lub liczba, użyłbym tego:

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

I dla niektórych przykładów:

isNumber(123);   //true
isNumber('123'); //true
isNumber('123a');//false
isNumber('');    //false
-2
Aryeh Beitz 15 maj 2017, 05:22

Lubię używać tego prostego rozwiązania:

var myString = "test";
if(myString.constructor === String)
{
     //It's a string
}
17
ScottyG 7 listopad 2017, 16:01

Jest to świetny przykład, dlaczego kwestie wydajności:

Robiąc coś tak prostego, jak test dla ciągów może być drogi, jeśli nie zostanie wykonany prawidłowo.

Na przykład, jeśli chciałem napisać funkcję do testowania, jeśli coś jest sznurkiem, mógłbym to zrobić na dwa sposoby:

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

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

Oba są dość proste, więc co może mieć wpływ na wydajność? Ogólnie rzecz biorąc, rozmowy funkcyjne mogą być drogie, zwłaszcza jeśli nie wiesz, co się dzieje w środku. W pierwszym przykładzie istnieje wywołanie funkcji do metody Tostrushing obiektu. W drugim przykładzie nie ma połączeń funkcyjnych, ponieważ TypeOf i Instanceof są operatorzy. Operatorzy są znacznie szybsze niż połączenia funkcyjne.

Po przetestowaniu wydajności przykład 1 wynosi 79% wolniejszy niż przykład 2!

Zobacz testy: https://jsperf.com/isstringtype

16
Paul Rooney 25 październik 2018, 01:00
if (s && typeof s.valueOf() === "string") {
  // s is a string
}

Działa zarówno dla literówków strunowych let s = 'blah' i do ciągów obiektów let s = new String('blah')

15
wheelmaker 16 listopad 2019, 15:49

Wykonano z 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
8
Benj Sicam 11 wrzesień 2015, 01:16

Myślę, że roztwór @Custommander powinien wystarczyć w 90% swoich przypadków:

typeof str === 'string'

Powinien służyć prawem (po prostu od zwykle nie ma powodu, aby mieć new String('something') w swoim kodzie).

Jeśli jesteś zainteresowany obsługą obiektu String, jak również (na przykład oczekujesz, że niektóre Var z trzeciej imprezy) następnie za pomocą Lodasha, ponieważ @ ClearCloud8 Sugerowany wydaje się jasne, proste i eleganckie rozwiązanie.

Zaproponowałem jednak ostrożnie z bibliotekami, takimi jak Lodash z powodu ich wielkości. Zamiast robić

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

Który przynosi cały ogromny obiekt Lodash, sugerowałem coś takiego:

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

Z prostym pakietem powinieneś być w porządku (odnoszę się tutaj do Kodeksu Klienta).

7
Erez Cohen 22 lipiec 2019, 20:45

Odkryłem też, że to też działa dobrze i jest znacznie krótsza niż inne przykłady.

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

Połączanie się na pustych cytatów zamienia wartość w ciągu. Jeśli myVar jest już sznurkiem, a jeśli stwierdzenie jest udane.

6
Chris Dolphin 27 wrzesień 2013, 18:09

Jeśli pracujesz nad środowiskiem węzła.

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

Edytuj: Jak wspomniano @Jehy, jest to przestarzałe od V4.

5
David 30 styczeń 2017, 20:45

Poniższa metoda sprawdzi, czy jakakolwiek zmienna jest ciągiem (, w tym zmienne, które nie istnieją ).

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
4
Grant Miller 2 marzec 2019, 17:57

Uważam tę prostą technikę przydatną do napisania-sprawdzenia dla 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

Ta sama technika działa dla numer

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

I dla 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

Tak samo dla obiekt -

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

NB, Regexps, tablice i funkcje są również uważane za obiekty.

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)    

Ale sprawdzanie tablicy jest nieco inna -

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

Ta technika robi nie działa dla funkcje

Function(x) === x // always false
4
Thank you 10 sierpień 2019, 15:34
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))
3
Jake 22 grudzień 2015, 04:59