检查变量是否是JavaScript中的字符串

时间:2010-10-30 14:36:35

标签: javascript

如何确定变量是否为JavaScript中的字符串或其他内容?

26 个答案:

答案 0 :(得分:1643)

这对我有用:

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

答案 1 :(得分:1362)

您可以使用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"

来自this webpage的示例。 (虽然稍微修改了示例)。

在使用new String()创建的字符串的情况下,这将无法正常工作,但这很少用于 [1] [2] 。如果您愿意,请参阅其他答案,了解如何处理这些问题。


  1. Google JavaScript样式指南says to never use primitive object wrappers
  2. Douglas Crockford recommended that primitive object wrappers be deprecated

答案 2 :(得分:124)

由于有580多人投票给出了错误的答案,而且有800多人投票赞成了一个有效但枪口式的答案,我认为以一种每个人都能理解的简单形式重新回答我的答案是值得的。

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

或者,内联(我有一个UltiSnip设置):

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

仅供参考,Pablo Santa Cruz的回答是错误的,因为typeof new String("string")object

DRAX的答案是准确和实用的,应该是正确的答案(因为Pablo Santa Cruz绝对是错误的,我不会反对普遍投票。)

然而,这个答案也是绝对正确的,实际上是最好的答案(可能除了建议使用lodash / underscore)。 免责声明:我为lodash 4代码库做出了贡献。

我的原始答案(显然是在很多人头上飞过)如下:

我从underscore.js转发了这个:

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

这将定义isString,isNumber等。


在Node.js中,这可以作为模块实现:

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

答案 3 :(得分:78)

我建议使用 jQuery lodash / Underscore 中的内置函数。它们使用起来更简单,更易于阅读。

这两个函数都将处理DRAX提到的情况......也就是说,它们检查(A)变量是字符串文字还是(B)它是String对象的一个​​实例。在任何一种情况下,这些函数都正确地将值标识为字符串。

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

有关详细信息,请参阅lodash Documentation for _.isString()

有关详细信息,请参阅jQuery Documentation for $.type()

答案 4 :(得分:31)

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

我在这里看到了:

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

答案 5 :(得分:21)

最佳方式:

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

每个都是由适当的类函数构造的,比如“new Object()”等。

另外,Duck-Typing: “如果它看起来像一只鸭子,像鸭子一样走路,闻起来像一只鸭子 - 它必须是一个阵列” 含义,检查其属性。

希望这有帮助。

编辑; 2016年12月5日

请记住,您也可以始终使用方法组合。以下是使用 typeof 内联映射操作的示例:

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

这是一个使用内联地图的“真实世界”示例:

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

此函数将使用[custom]“type-casting” - 而不是“type - / - value-mapping” - 来确定变量是否实际“存在”。现在你可以在null&amp;之间拆分那个讨厌的头发了。 0

很多时候你甚至不关心它的类型。绕过打字的另一种方法是组合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) ...;
}

Number.prototype String.prototype都有.toString() method。您只需确保数字的字符串等效值相同,然后确保将其作为http传递到Number函数中。换句话说,我们甚至没有关心它的类型。

希望能为您提供更多合作:)

答案 6 :(得分:11)

我喜欢使用这个简单的解决方案:

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

答案 7 :(得分:10)

性能

今天2020.09.17,我针对选定的解决方案在Chrome v85,Safari v13.1.2和Firefox v80的MacOs HighSierra 10.13.6上进行了测试。

结果

对于所有浏览器(和两个测试用例)

  • 解决方案typeof||instanceof(A,I)和x===x+''(H)是最快/最快的
  • 解决方案_.isString(lodash库)中等/快速
  • 解决方案B和K最慢

enter image description here

更新:2020.11.28我更新了x=123 Chrome列的结果-解决方案I之前可能存在错误值(= 69M太低)-我使用Chrome 86.0重复测试。

详细信息

我为解决方案执行2个测试用例 A B C D E F G H I J K L

  • 当变量是字符串时-您可以运行它HERE
  • 当变量不是字符串时-您可以运行HERE

以下代码段显示了解决方案之间的差异

// https://stackoverflow.com/a/9436948/860099
function A(x) {
  return (typeof x == 'string') || (x instanceof String)
}

// https://stackoverflow.com/a/17772086/860099
function B(x) {
  return Object.prototype.toString.call(x) === "[object String]"
}

// https://stackoverflow.com/a/20958909/860099
function C(x) {
  return _.isString(x);
}

// https://stackoverflow.com/a/20958909/860099
function D(x) {
  return $.type(x) === "string";
}

// https://stackoverflow.com/a/16215800/860099
function E(x) {
  return x?.constructor === String;
}

// https://stackoverflow.com/a/42493631/860099
function F(x){
  return x?.charAt != null
}


// https://stackoverflow.com/a/57443488/860099
function G(x){
  return String(x) === x
}

// https://stackoverflow.com/a/19057360/860099
function H(x){
  return x === x + ''
}

// https://stackoverflow.com/a/4059166/860099
function I(x) {
  return typeof x == 'string'
}

// https://stackoverflow.com/a/28722301/860099
function J(x){
  return x === x?.toString()
}

// https://stackoverflow.com/a/58892465/860099
function K(x){
  return x && typeof x.valueOf() === "string"
}

// https://stackoverflow.com/a/9436948/860099
function L(x) {
  return x instanceof String
}

// ------------------
//     PRESENTATION
// ------------------

console.log('Solutions results for different inputs \n\n');
console.log("'abc' Str  ''  ' ' '1' '0'  1   0   {} [] true false null undef");

let tests = [ 'abc', new String("abc"),'',' ','1','0',1,0,{},[],true,false,null,undefined];

[A,B,C,D,E,F,G,H,I,J,K,L].map(f=> {  
console.log(
  `${f.name}   ` + tests.map(v=> (1*!!f(v)) ).join`   `
)})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>


This shippet only presents functions used in performance tests - it not perform tests itself!

这是铬的示例结果

enter image description here

答案 8 :(得分:10)

坦白地说,为什么我不会简单地使用typeof

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

是的,它将无法使用对象包装的字符串(例如new String('foo')),但是这些被广泛认为是一种不好的做法,大多数现代开发工具很可能会阻止其使用。 (如果看到一个,请修复它!)

Object.prototype.toString窍门是所有前端开发人员都被认为有一天从事职业的罪名,但不要让它被聪明的骗子欺骗了您:它会在某些事情发生后立即崩溃猴子修补对象原型:

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

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

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

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

答案 9 :(得分:9)

这是表现重要性的一个很好的例子:

如果没有正确完成,做一些像测试字符串一样简单的事情可能会很昂贵。

例如,如果我想编写一个函数来测试某些东西是否为字符串,我可以通过以下两种方式之一来完成:

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

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

这两个都很直接,所以可能会影响性能?一般来说,函数调用可能很昂贵,特别是如果你不知道里面发生了什么。在第一个例子中,有一个函数调用Object的toString方法。在第二个示例中,没有函数调用,因为typeof和instanceof是运算符。运算符明显快于函数调用。

测试性能时,示例1比示例2慢79%!

参见测试:https://jsperf.com/isstringtype

答案 10 :(得分:7)

取自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

答案 11 :(得分:4)

如果你在node.js环境中工作,你可以在utils中使用内置函数isString。

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

编辑:正如@Jehy所提到的,自v4以来已弃用。

答案 12 :(得分:4)

我也发现这也很好,而且比其他例子短得多。

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

通过连接空引号,它将值转换为字符串。如果myVar已经是字符串,则if语句成功。

答案 13 :(得分:4)

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

适用于字符串文字let s = 'blah'和对象字符串let s = new String('blah')

答案 14 :(得分:3)

一个简单的解决方案是:

var x = "hello"

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

答案 15 :(得分: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))

答案 16 :(得分:3)

在这里,我将走另一条路,其余的尝试去告诉变量是特定类型还是特定类型的成员。
JS建立在鸭类上。如果某些东西像字符串一样嘎嘎响,我们可以并且应该像字符串一样使用它。

7是字符串吗?那么/\d/.test(7)为什么起作用?
{toString:()=>('hello there')}是字符串吗?那么({toString:()=>('hello there')}) + '\ngeneral kenobi!'为什么起作用?
这些不是关于应该上述工作的问题,重点是它们。

所以我做了一个duckyString() function
下面我测试了许多其他答案无法解决的情况。对于每个代码:

  • 设置类似字符串的变量
  • 在其上运行相同的字符串操作,然后在真实的字符串上进行比较以比较输出(证明它们可以像字符串一样对待)
  • 将类似字符串的字符串转换为真实字符串,以向您展示duckyString(),以规范需要真实字符串的代码的输入
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');

这与!!x不同,而不是x===true,并测试某些东西是否类似于数组 ,而不需要实际的数组。
jQuery对象;他们是数组吗?不,他们够好吗?是的,您可以通过Array.prototype函数运行它们。
正是这种灵活性赋予了JS强大的功能,并且测试 for 字符串特别使您的代码的互操作性降低。

上面的输出是:

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"

所以,这全都与为什么有关,您想知道某个东西是否是字符串。
如果像我一样,您是从Google来到这里的,并且想看看某物是否是类似于字符串的,这就是答案。
除非您使用的是很长或深度嵌套的char数组,否则它甚至都不昂贵。
这是因为只有if语句,没有像.toString()这样的函数调用。
除非您尝试查看具有仅包含toString()或多字节字符的对象的char数组,在这种情况下,除了制作字符串和计数之外,没有其他方法可以检查字节分别组成的字符

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

包括的选项

  • 询问哪种方法认为它是字符串y
  • 排除字符串检测方法(例如,如果您不喜欢.toString()

这里有更多测试,因为我是一名完成论者:

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});
  • 所有负面案例似乎都可以解释
  • 这应该在> = IE8的浏览器上运行
  • 在支持字符串迭代器的浏览器中支持具有多个字节的Char数组

输出:

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"

答案 17 :(得分:3)

我发现这种简单的技术对于类型检查 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

相同的技术也适用于 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

对于 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

对象-

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

NB,正则表达式,数组和函数也被视为对象。

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)    

但是,检查 Array 有点不同-

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

该技术对功能不起作用 --

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

答案 18 :(得分:2)

以下方法将检查是否有任何变量是字符串(包括不存在的变量)。

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

答案 19 :(得分:1)

一种简单快速的测试方法是使用构造函数名称属性。

let x = "abc";
console.log(x.constructor.name === "String"); // true

let y = new String('abc');
console.log(y.constructor.name === "String"); // true

性能

enter image description here

答案 20 :(得分:0)

我认为@customcommander解决方案可以满足您90%的情况:

dataType: 'json'

应该为您服务正确(因为通常没有理由在代码中使用typeof str === 'string' )。

如果您也有兴趣处理new String('something')对象(例如,您希望第三者提供一些变量),则使用lodash,因为@ ClearCloud8建议看起来是一个清晰,简单而优雅的解决方案。

但是,我建议您谨慎使用lodash之类的库,因为它们的大小很大。而不是

String

带了整个巨大的lodash对象,我建议使用类似的东西

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

通过简单的捆绑,您应该没事(我在这里指的是客户端代码)。

答案 21 :(得分:0)

Typechecker助手:

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

用法:

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

此外,如果您希望它具有递归性(例如作为对象的数组),则可以使用instanceof

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

答案 22 :(得分:0)

这对我来说已经足够了。

警告:这不是一个完美的解决方案。 请参阅我的帖子底部。

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

您可以像下面这样使用它。

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

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

警告:在以下情况下,此方法无法正常工作:

close

答案 23 :(得分:0)

为了扩展@ DRAX的answer,我会这样做:

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

它还会考虑nullundefined类型,它会处理非字符串类型,例如0

答案 24 :(得分:-1)

您可以使用此功能来确定任何东西的类型:

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

答案 25 :(得分:-2)

我不确定你是不是想知道它是string类型,无论其内容如何,​​或者它的内容是数字还是字符串,无论其类型如何。

因此要知道它的类型是否为字符串,已经得到了答案。
但要知道基于其内容的字符串或数字,我会用这个:

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

以及一些例子:

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