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

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

2384082 次浏览

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

来自此网页的示例(示例略有修改)。

在使用new String()创建的字符串的情况下,这不会像预期的那样工作,但这很少使用,并且建议反对[1][2]。如果您愿意,请参阅其他答案以了解如何处理这些。


  1. Google JavaScript风格指南说永远不要使用原始对象包装器
  2. 道格拉斯·克罗克福德建议不建议使用原始对象包装器

这是对我有用的:

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

最佳方式:

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()”等。

还有鸭子打字:“如果它看起来像一只鸭子,走路像一只鸭子,闻起来像一只鸭子-它必须是一个阵列。意思是,检查它的属性。

希望这有帮助。

编辑;12/05/2016

请记住,您也可以随时使用方法的组合。这是将内联映射操作与typeof一起使用的示例:

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

这是一个使用inline-map的更“真实”的例子:

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

这个函数将使用[自定义]“类型转换”——更确切地说,“类型/值映射”——来确定变量是否真的“存在”。现在您可以在null0之间分割那讨厌的头发!

很多次你甚至不关心它的类型。另一种规避键入的方法是组合Duck-Type集:

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

Number.prototypeString.prototype都有一个.toString() method。您只需确保数字的字符串等效值相同,然后确保将其作为Number传递给http函数。换句话说,我们甚至没有照顾它的类型是什么。

希望能给你更多的工作:)

由于有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绝对是不正确的,我不会反对民众投票。

然而,这个答案也是绝对正确的,实际上是最好的答案(除了,也许,对于使用豆沙/强调的建议)。

我最初的答案(显然飞过了很多人的头)如下:

我从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;}, {});

[编辑]:Object.prototype.toString.call(x)也可以在函数和异步函数之间进行划分:

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

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

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

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

我建议使用jQuery洛达什/下划线中的内置函数。它们使用起来更简单,也更容易阅读。

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

Lodash/Underscore.js

if(_.isString(myVar))//it's a stringelse//it's something else

jQuery

if($.type(myVar) === "string")//it's a stringelse//it's something else

查看_. isString()的Lodash文档了解更多详情。

查看$. type()的jQuery文档了解更多详情。

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

我在这里看到:

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

只是为了扩展@DRAX的回答,我会这样做:

function isWhitespaceEmptyString(str){//RETURN://      = 'true' if 'str' is empty string, null, undefined, or consists of white-spaces onlyreturn str ? !(/\S/.test(str)) : (str === "" || str === null || str === undefined);}

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

一个简单的解决方案是:

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

摘自Lodash:

function isString(val) {return typeof val === 'string' || ((!!val && typeof val === 'object') && Object.prototype.toString.call(val) === '[object String]');}
console.log(isString('hello world!')); // trueconsole.log(isString(new String('hello world'))); // true
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))

编辑:当前的方法是typeof value === 'string'。例如:

const str = 'hello';if (typeof str === 'string') { ... }

自节点v4以来,以下已被弃用。

如果您在node.js环境中工作,您可以简单地使用utils中的内置函数isString。

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

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

所以要知道它的类型是否是字符串,这已经被回答了。
但是要根据它的内容知道它是字符串还是数字,我会使用这个:

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

举几个例子:

isNumber(123);   //trueisNumber('123'); //trueisNumber('123a');//falseisNumber('');    //false

我喜欢用这个简单的方法:

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

这是一个很好的例子,说明为什么性能很重要:

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

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

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

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

这两个都很简单,那么可能会影响性能呢?一般来说,函数调用可能会很昂贵,特别是如果你不知道里面发生了什么。在第一个例子中,有一个对Object的toString方法的函数调用。在第二个例子中,没有函数调用,因为typeof和instance of是运算符。运算符比函数调用快得多。

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

查看测试:https://jsperf.com/isstringtype

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

const is_string = value => {try {return typeof value() === 'string';} catch (error) {return false;}};
let example = 'Hello, world!';
console.log(is_string(() => example)); // trueconsole.log(is_string(() => variable_doesnt_exist)); // false

这对我来说已经足够好了。

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

Object.prototype.isString = function() { return false; };String.prototype.isString = function() { return true; };
var isString = function(a) {return (a !== null) && (a !== undefined) && a.isString();};

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

//return falseisString(null);isString(void 0);isString(-123);isString(0);isString(true);isString(false);isString([]);isString({});isString(function() {});isString(0/0);
//return trueisString("");isString(new String("ABC"));

警告:这在以下情况下不正确:

//this is not a stringvar obj = {//but returns true lolisString: function(){ return true; }}
isString(obj) //should be false, but true

我真的不明白为什么在这种情况下不简单地使用typeof

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

是的,它会在对象包装字符串(例如new String('foo'))上失败,但这些被广泛认为是一种糟糕的做法,大多数现代开发工具可能会阻止它们的使用。(如果你看到一个,只是修复它!)

Object.prototype.toString技巧是所有前端开发人员在他们的职业生涯中有一天都会犯的错误,但不要让它被它的聪明所愚弄:一旦有什么东西对Object原型进行猴子修补,它就会崩溃:

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

您可以使用此函数来确定任何内容的类型:

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

要检查变量是否为字符串:

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

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

检查其他类型:

type(null) //nulltype(undefined) //undefinedtype([]) //arraytype({}) //objecttype(function() {}) //functiontype(123) //numbertype(new Number(123)) //numbertype(/some_regex/) //regexptype(Symbol("foo")) //symbol

我发现这个简单的技术对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 failedtest(0)             // assertion failedtest(/some regex/)  // assertion failedtest([ 5, 6 ])      // assertion failedtest({ a: 1 })      // assertion failedtest(x => x + 1)    // assertion failed

同样的技术也适用于数量-

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 failedtest(123)test(0)test(/some regex/)  // assertion failedtest([ 5, 6 ])      // assertion failedtest({ a: 1 })      // assertion failedtest(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 failedtest(123)           // assertion failedtest(0)             // assertion failedtest(/some regex/)test([ 5, 6 ])      // assertion failedtest({ a: 1 })      // assertion failedtest(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 failedtest(123)           // assertion failedtest(0)             // assertion failedtest(/some regex/)test([ 5, 6 ])test({ a: 1 })test(x => x + 1)    

但是,检查数组有点不同-

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 failedtest(123)           // assertion failedtest(0)             // assertion failedtest(/some regex/)  // assertion failedtest([ 5, 6 ])test({ a: 1 })      // assertion failedtest(x => x + 1)    // assertion failed

这种技术没有函数有效-

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

对于@Faither-

const fmt = JSON.stringify
function test1() {const a = "1"const b = 1console.log(`Number(${fmt(a)}) === ${fmt(b)}`, Number(a) === b) // true}
function test2() {const a = "1"const b = 1console.log(`Number.isInteger(${fmt(a)})`, Number.isInteger(a)) // falseconsole.log(`Number.isInteger(${fmt(b)})`, Number.isInteger(b)) // true}
function test3() {name = 1 // global name will always be a stringconsole.log(fmt(name)) // "1"console.log(`String(${fmt(name)}) === ${fmt(name)}`, String(name) === name) // true}
function test4() {const name = 1 // local nameconsole.log(fmt(name)) // 1console.log(`String(${fmt(name)}) === ${fmt(name)}`, String(name) === name) // false}
test1(); test2(); test3(); test4()

Typechecker助手:

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

用法:

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

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

['cs'] instanceof Object //true

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

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

我将在这里采用不同的方法,尝试判断变量是特定类型还是特定集合的成员。
JS是建立在Ducktyping之上的;如果有什么东西像字符串一样嘎嘎叫,我们可以也应该像字符串一样使用它。

7是字符串吗?那为什么/\d/.test(7)起作用?
{toString:()=>('hello there')}是字符串吗?那为什么({toString:()=>('hello there')}) + '\ngeneral kenobi!'起作用?
下面我测试了许多其他答案无法满足的情况。对于每个代码:

  • 设置类似字符串的变量
  • 对其运行相同的字符串操作和一个真正的字符串来比较输出(证明它们可以像字符串一样对待)
  • 将类似字符串的字符串转换为真实字符串,以向您显示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');

这与!!xx===true相同,并测试某些东西是否是数组-喜欢而不是需要实际数组。
jQuery对象;它们是数组吗?不。它们足够好吗?是的,您可以通过Array.prototype函数很好地运行它们。
正是这种灵活性赋予了JS强大的功能,测试进行字符串特别使您的代码不那么具有互操作性。

上面的输出是:

hEllo thErE hEllo thErEIs string? true "hello there"
OH MY OH MYIs string? true "oh my"
368 is a big number 368 is a big numberIs string? true "368"
56839 56839Is string? true "😇"
0 0Is string? true "10"

所以,这都是关于为什么你想知道某个东西是否是字符串。
如果,像我一样,你从谷歌来到这里,想看看什么是线状,这里有一个答案。它甚至不昂贵,除非您使用非常长或深度嵌套的char数组。
这是因为它都是if语句,没有像.toString()这样的函数调用。
除非你试图查看一个char数组中的对象是否只有toString()或多字节字符,在这种情况下,除了制作字符串和计算字节组成的字符之外,没有其他方法可以检查

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 stringelse if (!unacceptable.is &&(typeof string == 'string' || string instanceof String))type = 'is';
//tests if `string + ''` or `/./.test(string)` is validelse if (!unacceptable.to &&string.toString && typeof string.toString == 'function' && string.toString != Object.prototype.toString)type = 'to';
//tests if `[...string]` is validelse if (!unacceptable.chars &&(string.length > 0 || string.length == 0)) {type = 'chars';//for each charfor (var index = 0; type && index < string.length; ++index) {var char = string[index];
//efficiently get its lengthvar length = ((duckyString(char, false, {to:true})) ?char :duckyString(char, true) || {}).length;
if (length == 1)continue;
//unicode surrogate-pair supportchar = 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 stringif (!(type && normalise))//return truthy or falsy with <type>/null if they want why it's truereturn (normalise == null) ? type != null : type;
//perform conversionswitch (type) {case 'is':return string;case 'to':return string.toString();case 'chars':return Array.from(string).join('');}}

包括选项以

  • 询问哪个方法认为它是string-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上运行
  • 具有字符串迭代器支持的浏览器支持具有多字节的字符数组

输出:

Edge-case testingis ""null nullnull nullto "0"chars ""chars "!"null nullchars ""to "false"null nullchars "😇"chars "123"to "1,2,3"

性能

今天2020.09.17我在Chromev85、Safariv13.1.2和Firefox v80上对MacO HighSierra 10.13.6进行测试,以获取所选解决方案。

搜索结果

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

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

在此处输入图片描述

更新:2020.11.28我更新了x=123 Chrome列的结果-对于解决方案I,之前可能有一个错误值(=69M太低)-我使用Chrome86.0重复测试。

详情

我为解决方案执行2个测试用例ABCDEFGHIJKL

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

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

// https://stackoverflow.com/a/9436948/860099function A(x) {return (typeof x == 'string') || (x instanceof String)}
// https://stackoverflow.com/a/17772086/860099function B(x) {return Object.prototype.toString.call(x) === "[object String]"}
// https://stackoverflow.com/a/20958909/860099function C(x) {return _.isString(x);}
// https://stackoverflow.com/a/20958909/860099function D(x) {return $.type(x) === "string";}
// https://stackoverflow.com/a/16215800/860099function E(x) {return x?.constructor === String;}
// https://stackoverflow.com/a/42493631/860099function F(x){return x?.charAt != null}

// https://stackoverflow.com/a/57443488/860099function G(x){return String(x) === x}
// https://stackoverflow.com/a/19057360/860099function H(x){return x === x + ''}
// https://stackoverflow.com/a/4059166/860099function I(x) {return typeof x == 'string'}
// https://stackoverflow.com/a/28722301/860099function J(x){return x === x?.toString()}
// https://stackoverflow.com/a/58892465/860099function K(x){return x && typeof x.valueOf() === "string"}
// https://stackoverflow.com/a/9436948/860099function 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!

以下是chrome的示例结果

在此处输入图片描述

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

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

性能

在此处输入图片描述

豆沙v4.0.0实现

// getTag.js
const toString = Object.prototype.toString;
/*** Gets the `toStringTag` of `value`.** @private* @param {*} value The value to query.* @returns {string} Returns the `toStringTag`.*/function getTag(value) {if (value == null) {return value === undefined? "[object Undefined]": "[object Null]";}return toString.call(value);}
// isString.js
import getTag from "./getTag.js";
/*** Checks if `value` is classified as a `String` primitive or object.** @since 0.1.0* @category Lang* @param {*} value The value to check.* @returns {boolean} Returns `true` if `value` is a string, else `false`.* @example** isString('abc')* // => true** isString(1)* // => false*/function isString(value) {const type = typeof value;return (type === "string" || (type === "object" &&value != null &&!Array.isArray(value) &&getTag(value) == "[object String]"));}
export default isString;

只有没有任何数字的字符串的代码

isNaN("A") = true;parseInt("A") = NaN;isNaN(NaN) = true;

所以我们可以使用isNaN(parseInt())只包含字符串

let ignoreNumbers = "ad123a4m";
let ign = ignoreNumbers.split("").map((ele) => isNaN(parseInt(ele)) ? ele : "").join("");
console.log(ign);

我有个技术很蠢。但很简单。

if(maybeAString.toUpperCase)weHaveAString(maybeAString)

是的,它远非完美。但它直截了当。

我们也可以使用isFinite()而不是typeof或isNAN()点击这里:

var name="somename",trickyName="123", invalidName="123abc";
typeof name == typeof trickyName == typeof invalidName == "string" 🤷‍♀️
isNAN(name)==trueisNAN(trickyName)==falseisNAN(invalidName)==true 👀

在哪里:

isFinite(name) == falseisFinite(trickyName)== trueisFinite(invalidName)== true

所以我们可以做:

if(!isFinite(/*any string*/))console.log("it is string type for sure")

注意:

    isFinite("asd123")==falseisNAN("asd123")==true