2822

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

0

35个答案35

重置为默认值
2951

这对我来说很有效:

if(typeofmyVar==='string'||myVar instanceofString)//这是一根绳子其他的//这是另一回事

//测试此方法:让isString=value=>typeofvalue==='string'||valueinstanceofString;let falseCase=[[“null”,null],[“未定义”,未定义],[“对象”,{a:1,b:2}],[“数组”,[1,2,3]],['数字',123],[“零”,0],[“RegExp”,新RegExp(“hello”)],[“number with valueOf returning string”,Object.assign(10,{valueOf:()=>“abc”})],['伪装成字符串的对象',{constructor:string}]];让trueCase=[['空文本字符串',''],['unicode string literal',string.fromCharCode(10000)],['空的装箱字符串',新字符串('')],[“unicode装箱字符串”,新字符串(string.fromCharCode(10000))],['带覆盖“constructor”的字符串',Object.assign('hi',{constructor:Array})],['string with overrided“toString”',Object.assign('hi',{toString:123})],['带覆盖“valueOf”'的字符串,Object.assign('hi',{valueOf:123})],['带覆盖“constructor”的字符串',Object.assign('hi',{constructor:RegExp})],[“代理字符串”,new Proxy(new string('hello'),{})],];console.log('负面测试:');for(falseCases的let[name,val]){console.log(`Test${name}:\n预期:false\n获得:${isString(val)}`);}console.log('\nPOSITIVE TESTS:');for(let[name,val]of trueCases){console.log(`Test${name}:\n期望:true\n得到:${isString(val)}`);}

44
  • 172
    “myVar instanceof String”是否在“typeof myVar=='String'”之外做任何事情?
    – 第六名
    评论 2012年4月25日13:59
  • 127
    @我记得。在JavaScript中,可以有字符串的变量类型或字符串类的对象类型(相同的东西-都是字符串-但定义不同),这就是为什么要进行双重检查的原因。 评论 2012年4月26日10:04
  • 59
    var somevar=new String('somestring')console.log(typeof somevar)//对象 评论 2013年7月9日8:52
  • 159
    -1因为运算符检查这里是没有意义的噪音,除非你遵循一些非常不寻常编码实践,而这个答案并不能解释它做什么或为什么你会使用它。你需要它的唯一原因是如果你使用对象标记字符串,但对象标记字符串是一个没有价值的特性,没有人使用,谷歌和克罗福德都谴责这是一个糟糕的实践(google-styleguide.googlecode.com/svn/trunk/…,crokford.com/javascript/recommend.html). 评论 2015年8月16日17:34
  • 222
    我强烈反对编写正确处理不太可能出现的情况的可靠代码是应该避免的。检查两者类型运算符如果你的代码可能被其他人调用,我觉得这是个好建议@MarkAmery的邮递信息如果你问“我刚才是什么?”邮递信息d?天?“-但你应该在接口上处理,不允许传播。在其他地方,处理非弃用的编码方法似乎是正确的,即使一些JS美学专家不赞成它们。千万不要将代码注释为接受String,除非它真的接受了! 评论 2015年9月4日4:11
2428

你可以使用类型操作员:

var booleanValue=true;var数值=354;var stringValue=“这是一个字符串”;var stringObject=new String(“这是一个字符串对象”);console.log(typeofbooleanValue)//显示“boolean”console.log(typeofnumericalValue)//显示“数字”console.log(typeofstringValue)//显示“string”console.log(字符串对象类型)//显示“对象”

示例来自这个网页(但示例稍作修改)。

对于使用创建的字符串,这将无法按预期工作新建字符串(),但很少使用,建议不要使用[1][2]。如果您愿意,请参阅其他答案以了解如何处理这些问题。

//测试此方法:让isString=value=>typeof value===“字符串”;let falseCase=[[“null”,null],[“未定义”,未定义],[“对象”,{a:1,b:2}],[“数组”,[1,2,3]],[“数字”,123],[“零”,0],['RegExp',新RegExp('hello')],[“number with valueOf returning string”,Object.assign(10,{valueOf:()=>“abc”})],['伪装成字符串的对象',{constructor:string}]];让trueCase=[['空文本字符串',''],['unicode string literal',string.fromCharCode(10000)],[“空装箱字符串”,新字符串(“”)],[“unicode装箱字符串”,新字符串(string.fromCharCode(10000))],['带覆盖“constructor”的字符串',Object.assign('hi',{constructor:Array})],['string with overrided“toString”',Object.assign('hi',{toString:123})],['带覆盖“valueOf”'的字符串,Object.assign('hi',{valueOf:123})],['带覆盖“constructor”的字符串',Object.assign('hi',{constructor:RegExp})],[“代理字符串”,new Proxy(new string('hello'),{})],];console.log('负面测试:');for(falseCases的let[name,val]){console.log(`Test${name}:\n预期:false\n获得:${isString(val)}`);}console.log('\nPOSITIVE TESTS:');for(let[name,val]of trueCases){console.log(`Test${name}:\n期望:true\n得到:${isString(val)}`);}


  1. 谷歌JavaScript风格指南说永远不要使用原始对象包装器.
  2. 道格拉斯·克罗克福德建议弃用基本对象包装器.
13
  • 54
    @Wolfy87请注意,在某些情况下,typeof stringValue可能返回“object”而不是“string”。请参阅对我的回答的评论。 评论 2012年4月26日10:07
  • 226
    我喜欢的答案。反对它的理由是,它对于诸如新字符串('foo'),但这并不重要,因为对象映射字符串是一个毫无价值的特性,您不应该使用它。谷歌风格指南禁止他们道格拉斯·克罗克福德希望他们弃用没有库使用它们。假装它们不存在,然后使用类型没有恐惧。 评论 2014年6月6日21时13分
  • 8
    没有道格拉斯·克罗克福德建议类型被否决也? 评论 2017年10月2日9:11
  • 12
    @丹尼尔,因为他提出了一个可以解决一些问题的替代方案,而不是因为他原则上反对。 评论 2017年12月6日17:30
  • 6
    如果它让你头疼,99.99%的时间是因为你没有正确地构造代码。这并不是NaN存在和做它所做的事情的错,这是你下次处理可能产生它的代码时应该注意、学习和牢记的事情。 评论 2018年10月3日15:44
262
函数isString(x){return Object.protype.toString.call(x)===“[Object String]”}

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

Object.prototype.toString.call(myVar)===“[Object String]”

仅供参考,巴勃罗·圣克鲁斯的回答是错误的,因为新字符串的类型(“字符串”)对象

DRAX的答案准确且实用,应该是正确的答案(因为巴勃罗·圣克鲁斯(Pablo Santa Cruz)绝对是错误的,我不会反对公众投票。)

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

我最初的回答(显然是从很多人的头上飞过去的)如下:

我从underscore.js中转码了这个:

['Arguments','Function','String','Number','Date','RegExp'].forEach(函数(名称){窗口['is'+名称]=函数(obj){return toString.call(obj)=='[对象'+name+']';}; });

这将定义isString、isNumber等。


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

模块导出=[“参数”,“函数”,“字符串”,“数字”,'日期',“RegExp”].reduce((obj,name)=>{obj['是'+name]=x=>toString.call(x)=='[对象'+name+']';返回对象;}, {});

[编辑]: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))

//测试此方法:函数isString(x){return Object.prototype.toString.call(x)===“[Object String]”}let falseCase=[[“null”,null],[“未定义”,未定义],[“对象”,{a:1,b:2}],['数组',[1,2,3],['数字',123],[“零”,0],['RegExp',新RegExp('hello')],[“number with valueOf returning string”,Object.assign(10,{valueOf:()=>“abc”})],['伪装成字符串的对象',{constructor:string}]];让trueCase=[['空文本字符串',''],['unicode string literal',string.fromCharCode(10000)],[“空装箱字符串”,新字符串(“”)],[“unicode装箱字符串”,新字符串(string.fromCharCode(10000))],['带覆盖“constructor”的字符串',Object.assign('hi',{constructor:Array})],['string with overrided“toString”',Object.assign('hi',{toString:123})],['带覆盖“valueOf”'的字符串,Object.assign('hi',{valueOf:123})],['带覆盖“constructor”的字符串',Object.assign('hi',{constructor:RegExp})],[“代理字符串”,new Proxy(new string('hello'),{})],];console.log('负面测试:');for(falseCases的let[name,val]){console.log(`Test${name}:\n预期:false\n获得:${isString(val)}`);}console.log('\nPOSITIVE TESTS:');for(let[name,val]of trueCases){console.log(`Test${name}:\n期望:true\n得到:${isString(val)}`);}

28
  • 22
    你推荐underscore.js(出于什么奇怪的原因?)但你在这里不使用它。此外,您还使用函数污染了全局命名空间。在node.js中,您将创建一个具有所有这些功能的模块(您可以使用全局窗口而不是窗口但这对于解决一个你一开始就不应该遇到的问题来说是一个糟糕的方法。 评论 2013年7月21日12:13
  • 24
    @Benjamin Gruenbaum我来找OP问题的答案,但不喜欢任何答案。因此,我检查了下划线的作用,认为它足够漂亮,可以进行一些提取和修改(以避免必须加载下划线库)。我会澄清我的帖子。
    – 亲欧派
    评论 2013年8月3日0:06
  • 35
    @亲欧人士,这怎么比DRAX的答案更好? 评论 2017年6月20日19:53
  • 7
    JS支持monkey补丁,因此可以重新定义到字符串在中对象.原型因此,我认为依赖到字符串检查对象的类型充其量是一种糟糕的做法。 评论 2018年7月26日1:44
  • 11
    我支持用“错误的答案”和“枪杆子式的答案”来更具体地指帖子,因为回复的数量已经过时了,然后解释为什么当你给出更好的答案时,这些答案是低劣的。我的两分钱。 评论 2019年11月26日22:13
96

我建议使用中的内置函数jQuery(jQuery)lodash/底芯。它们更易于使用和阅读。

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

lodash/Underscore.js

if(_.isString(myVar))//这是一根绳子其他的//这是另一回事

jQuery(jQuery)

if($.type(myVar)===“字符串”)//这是一根绳子其他的//是别的东西

请参见_.isString()的lodash文档了解更多详细信息。

请参见$.type()的jQuery文档了解更多详细信息。

14
  • 162
    这是JS社区问题的本质所在——对基本类型的检查是一个单行程序,只涉及语言构造(基本类型之一),但您建议使用外部库。如果有人已经使用了这些库中的一个,这可能是一个好主意,但下载它们只是为了这个目的,而不是简单地检查类型是一种过度技巧。 评论 2016年10月25日10:32
  • 6
    我会同意拉斐尔的观点。我到处都看到,使用这些外部库之一可以提高“可读性”。如果你知道JavaScript,那么它比你没有使用过的外部库更容易阅读。_.每个()一开始使用起来有点混乱,简单到_.isBoolean()混淆了我公司的开发人员。开发人员错误地认为,如果值是布尔值且为false,则该值为false。对我来说,英语比德语更容易阅读,因为我不懂德语。学习JavaScript,一切都会有意义。
    – 夏定忠
    评论 2017年4月6日16:33
  • 23
    @RafałWrzeszcz这些库被广泛使用,并提供了许多有用的(经过测试的)功能。尤其是洛达什。我不建议有人下载这个库只用于这个解决方案。。。。但我建议每个javascript开发人员下载这个库,看看他们遗漏了什么。)
    – 帕克尔
    评论 2017年5月24日10:27
  • 24
    你们都错过了像Lodash这样的图书馆的要点:而不是速度。不是“易于开发”。原因使用Lodash这样的库可以提供“防御能力”,防止出现会破坏js应用程序的问题。当您尝试对对象执行字符串操作时会发生致命错误(反之亦然),Lodash为防止这些错误提供了巨大的价值。 评论 2017年10月17日21:15
  • 14
    所有这些评论都是有效的,但是,伙计……只有使用JS,才建议使用第三方库来检查类型不要让你被嘲笑出开发室。 评论 2020年12月9日14:50
66

编辑:当前的方法是typeof value===“字符串”例如:

const str='hello';if(typeofstr==='string'){…}

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

如果您使用node.js环境,只需在utils中使用内置函数isString。

const-util=要求('util');if(util.isString(myVar)){}
  • 1
    有替代品吗? 评论 2017年11月9日23:09
  • 4
    文件上写着“使用typeof value===“字符串”而不是。" 评论 2018年10月30日22:50
  • 2
    x=新字符串('x');x.isString(x);收益。有util.types.isStringObject()但这对返回falsex=“x”类型字符串。两个绝对不提供实用程序的实用程序函数。。。 评论 2020年4月17日7:29
49
函数isString(obj){return(Object.prototype.toString.call(obj)===“[Object String]”);}

我在这里看到了:

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

8
  • 4
    我认为这个解决方案是最强大的,因为它可以处理答案中提供的URL中提到的跨帧/跨窗口引用场景。
    – 哦,哦
    评论 2015年5月28日6:53
  • 1
    答案很好,看起来Undercore.js也使用了这个方法!
    – 达安
    评论 2016年7月1日13:25
  • @玲只是好奇,你为什么要用括号括起来Object.prototype.toString.call(obj)===“[Object String]”? 评论 2016年12月6日5:37
  • 2
    这与“亲欧人士”的回答有何不同? 评论 2018年5月7日19:45
  • 1
    @JonathanH——如果你看一下亲欧人士的答案的编辑历史,当时答案是这样写的,亲奥威尔说了一些相当复杂的话。直到2016年,这个答案才被编辑成包含这一点。所以凌应该获得荣誉! 评论 2021年7月10日21:57
39

最佳方式:

var s=“字符串”;变量a=[1,2,3];var o={key:'val'};(s.constructor===String)&&console.log('它是一个字符串');(a.constructor===数组)&&console.log('它是一个数组');(o.constructor===对象)&&console.log('它是一个对象');(o.constructor===数字||s.constructor===布尔值)&&console.log('这不会运行');

这些都是由其适当的类函数构造的,如“new Object()”等。

此外,鸭子打字:“如果它看起来像只鸭子,走路像鸭子,闻起来像鸭子-它一定是一个数组”也就是说,检查它的属性。

希望这能有所帮助。

编辑;12/05/2016

记住,你也可以随时使用各种方法的组合。下面是使用内联映射的操作类型:

var type={“number”:数学.sqrt.bind(数学),…}[数据类型];

下面是一个更“真实”的使用内联映射的示例:

功能是(基准){var isnt=!{null:true,undefined:true,'':true,false:false,0:false}[datum];返回!不是;}console.log(是(0),是(false),是[未定义],…);//>>真-真-假

这个函数将使用[custom]“type-casting”(而不是“type-/-value-mapping”)来判断变量是否真的“存在”。现在你可以把那讨厌的头发分开了无效的&0!

多次你甚至不在乎它的类型。另一种避免键入的方法是组合Duck-Type集合:

this.id=“998”;//使用数字或等效字符串函数get(id){if(!id||!id.toString)return;if(id.toString()===this.id.toString())http(id||+this.id);//如果(+id===+this.id)。。。;}

两者都有编号.原型 字符串.原型有一个.toString()方法。您只需确保数字的字符串等价物相同,然后确保将其传递到http协议作为编号换句话说,我们甚至没有照顾它的类型是什么。

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

5
  • 1
    您需要对普通旧数字进行其他检查,因为尝试获取其构造函数属性将失败:
    – 用户663031
    评论 2013年6月17日5时18分
  • @torazaburo刚才在Chrome控制台中对我来说工作得很好。是什么让你觉得它行不通? 评论 2014年6月6日21:04
  • 2
    @torazaburo你可能想玩弄断言((o.constructor===数字||s.constructor===布尔值)). 传说中,解析IntNaN公司是易碎但功能强大的工具。只需记住,Not-a-Number不是Not-a-Nomber,并且可以定义undefined。
    – 科迪
    评论 2014年6月11日23:18
  • 1
    a.constructor===数组错误,有时可能会失败,请使用Array.isArray参见web.mit.edu/jwalden/www/isArray.html 评论 2014年9月17日11:06
  • 1
    同意,这是不安全的。一个更好的方法是使用属性检查——这是目前唯一真正的故障安全方法。例子:if(thing.call){“它是一个函数”;}if(thing.defineProperties){'它是一个对象';}谢谢你的输入,axkibe!
    – 科迪
    评论 2014年9月29日19:31
39

我真的不明白为什么人们不直接使用类型在这种情况下:

if(类型str===“字符串”){返回42;}

是的,它会针对对象封装字符串失败(例如。新字符串('foo'))但这些都被广泛认为是一种糟糕的做法,大多数现代开发工具可能会阻碍其使用。(如果你看到一个,就把它修好!)

这个对象.原型.to字符串技巧是所有前端开发人员在职业生涯中的某一天都会犯下的错误,但不要让它通过巧妙的修饰来愚弄你:只要有什么东西与Object原型相匹配,它就会崩溃:

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

  • 4
    FWIW;反对一个解决方案,因为它可能被模仿对象原型所破坏,这是一个薄弱的论点。在动态语言中,几乎任何事情都可以被不该做的事情打破! 评论 2021年7月10日22:09
  • @工具制造商Steve Fair。你当然是对的。有人可以很容易地改变所有的原生原型,但什么都不起作用。我想我想说的是,在猴子修补仍然是常见做法的(JS)世界中,依赖这种技术充满了危险,当(更简单的)替代方案保证始终有效时,人们不应该暴露自己(AFAIK,你不能猴子修补类型). 尽管如此,我们还是抓住了这一点。谢谢您。 评论 2021年7月10日22:33
  • 1
    这是一种权衡:考虑到这两种方法并不总是返回相同的答案。所以这取决于你的“规格”——你所说的字符串是什么意思。“充满危险”在这种情况下似乎有点强硬。如果有人修改对象.原型.to字符串从而返回不同的结果。。。坦率地说,这是他们的问题!我想,可能性不应该成为决定使用何种方法的一个因素。(我个人不介意;我采用您展示的简单方法,但我不会编写库代码。) 评论 2021年7月12日16:03
32

性能

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

结果

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

  • 解决typeof实例(A、I)和x===x+''(H) 速度快/最快
  • 解决方案_.is字符串(lodash库)为中等/快速
  • 解决方案B和K最慢

在此处输入图像描述

更新:2020.11.28更新结果x=123铬列-用于解决方案之前可能有一个错误值(=69M太低)-我使用Chrome 86.0来重复测试。

细节

我为解决方案执行了2个测试用例A类 B类 C类 D类 E类 F类 H(H) J型 K(K) L(左)

以下片段介绍了解决方案之间的差异

// https://stackoverflow.com/a/9436948/860099函数A(x){return(typeofx=='string')||(xinstanceofString)}// https://stackoverflow.com/a/17772086/860099函数B(x){return Object.protype.toString.call(x)===“[Object String]”}// https://stackoverflow.com/a/20958909/860099函数C(x){return _.isString(x);}// https://stackoverflow.com/a/20958909/860099函数D(x){return$.type(x)===“string”;}// https://stackoverflow.com/a/16215800/860099函数E(x){返回x?。构造函数===字符串;}// https://stackoverflow.com/a/42493631/860099函数F(x){返回x?。charAt!=字符无效的}// https://stackoverflow.com/a/57443488/860099函数G(x){返回字符串(x)===x}// https://stackoverflow.com/a/19057360/860099函数H(x){返回x===x+''}// https://stackoverflow.com/a/4059166/860099函数I(x){返回类型x==“字符串”}// https://stackoverflow.com/a/28722301/860099函数J(x){返回x===x?。toString()}// https://stackoverflow.com/a/58892465/860099函数K(x){return x&&typeof x.valueOf()===“字符串”}// https://stackoverflow.com/a/9436948/860099函数L(x){返回字符串的x实例}// ------------------//演示文稿// ------------------console.log(“不同输入的解决方案结果”);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].映射(F=>{控制台.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-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovwww==“crossorigin=”anonymous“></script>这艘船只提供性能测试中使用的功能,它本身不执行测试!

下面是铬的示例结果

在此处输入图像描述

7
  • 你试过多次运行测试吗?我对在Chrome上运行x=123的策略“I”表示强烈怀疑。您得到69M,但对于案例A,您得到671M(这基本上是相同的代码,需要额外的测试)。在这里,该策略在Chrome中以x=123获胜。坦白地说,这并不是那么重要,但这只是一个提醒,性能微型基准测试很难做到正确。
    – 詹姆斯
    评论 2020年11月16日16:15
  • 是的-我过去多次运行测试-我现在也运行它-你现在有了-现在的结果是我好得多(我有674M的“I”)-我会更新这个(在空闲时间)-谢谢 评论 2020年11月16日16:28
  • @jwatkins-我用结果更新了表格-谢谢你的评论:) 评论 2020年11月28日21:26
  • 这非常非常有用-谢谢!但一些定时测试可能是不正确的,例如。x+''===x使用创建的字符串失败新字符串(“String”)。也许它应该局限于正确的测试,或者至少为每个测试的结果添加列,例如。无效的,未定义,123,新建对象()(所有人都应该给予)和"",“abc”,新字符串(“”),新字符串(“abc”)(所有人都应该给予真实的). 评论 2021年7月11日8:16
  • 测试A似乎从使用==而不是===-但不确定这是否重要。 评论 2021年7月11日8:18
19

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

如果操作不正确,对字符串进行测试这样简单的操作可能会代价高昂。

例如,如果我想编写一个函数来测试某个东西是否是字符串,我可以使用以下两种方法之一:

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

6
  • 测试链接死了,但我相信你。这种信息非常重要。我个人认为,如果这不是投票最多的答案,至少应该是对当前领先答案投票最多的评论。
    – 编码器
    评论 2019年1月3日17:00
  • typeof str===“string”||str字符串实例(可以去掉我喜欢的括号如果(..)案例);无论如何,检查第2条中的基本类型和对象类型是清楚和充分的。无论如何,这些检查应该是“罕见的”。 评论 2019年1月22日20:48
  • 1
    在这里是基准测试,在firefox上速度快30倍,2纳秒vs 50纳秒
    – 米兰胡
    评论 2020年10月2日19:37
  • 1
    是的,@MilaNautikus是唯一的问题布尔值(str.charCodeAt)解决方案是它不处理未定义/空的情况;否则我会说const isString=str=>str.charCodeAt!==未定义为了同样的表现
    – 布兰德
    评论 2020年10月5日18:27
  • 请注意运算符在边缘情况下,可以返回误报和漏报。例如someFunction.prototype=字符串原型;将使使用someFunction创建的任何新对象成为String的实例。换句话说(字符串的新someFunction实例)返回true。如果对在不同全局环境中创建的字符串对象进行测试,则会得到假阴性结果。因此,如果你需要100%确定这不是正确的方法。
    – PHP专家
    评论 4月26日21:06
16

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

var myString=“test”;if(myString.constructor===字符串){//这是一根绳子}
8
  • 4
    这与科迪4年后的回答有何不同? 评论 2018年5月7日19:36
  • 4
    @谢尔约翰科迪的回答很好。我的答案(全文)简明扼要。你问……:) 评论 2018年5月8日22:03
  • 1
    作为一种功能,这需要一种处理方式未定义无效的,并且仍然能够正确回答空字符串(两者都是''新字符串(“”)). 评论 2020年2月24日10:48
  • 1
    @MikeBeaton没问题:(mystring||false)&&mystring.constructor===字符串。我使用了false,以防在必须返回布尔值的函数中使用它。
    – 雅兰仕
    评论 2020年4月24日16:59
  • @MikeBeaton-空字符串会为返回不同的答案.构造函数? 这将非常令人惊讶。 评论 2021年7月10日22:12
16

我发现这个简单的技巧对类型检查很有用字符串-

如果x是字符串,则字符串(x)===x//true//其他情况下均为假

常数测试=x=>控制台资产(字符串(x)===x,`不是字符串:${x}`)测试(“一些字符串”)测试(123)//断言失败测试(0)//断言失败测试(/some regex/)//断言失败测试([5,6])//断言失败测试({a:1})//断言失败测试(x=>x+1)//断言失败

同样的技术适用于编号也是-

如果x是数字,则数字(x)===x//为真//其他情况下均为假

常量测试=x=>控制台资产(数量(x)===x,`不是数字:${x}`)test(“some string”)//断言失败测试(123)测试(0)测试(/some regex/)//断言失败测试([5,6])//断言失败测试({a:1})//断言失败测试(x=>x+1)//断言失败

对于注册Exp-

如果x是RegExp,则RegExp(x)===x//为true//其他情况下均为假

常数测试=x=>控制台资产(RegExp(x)===x,`不是regexp:${x}`)test(“some string”)//断言失败测试(123)//断言失败测试(0)//断言失败测试(/some regex/)测试([5,6])//断言失败测试({a:1})//断言失败测试(x=>x+1)//断言失败

与相同对象-

如果x是对象,则对象(x)===x//为true//其他情况下均为假

NB、regexp、数组和函数也被视为对象。

常数测试=x=>控制台资产(对象(x)===x,`不是对象:${x}`)test(“some string”)//断言失败测试(123)//断言失败测试(0)//断言失败测试(/some regex/)测试([5,6])测试({a:1})测试(x=>x+1)

但是,检查阵列有点不同-

Array.isArray(x)===x//true,如果x是数组//其他情况下均为假

常数测试=x=>控制台断言(数组.isArray(x),`不是数组:${x}`)test(“some string”)//断言失败测试(123)//断言失败测试(0)//断言失败测试(/some regex/)//断言失败测试([5,6])测试({a:1})//断言失败测试(x=>x+1)//断言失败

这项技术确实为…工作功能然而-

函数(x)===x//始终为false

对于@Faither-

const fmt=JSON.stringify功能测试1(){常数a=“1”常数b=1console.log(`数字(${fmt(a)})===${fmt(b)}`,数字(a)===b)//true}函数test2(){常数a=“1”常数b=1console.log(`Number.isInteger(${fmt(a)})`,Number.is Intege(a))//falseconsole.log(`Number.isInteger(${fmt(b)})`,Number.is Integer}功能测试3(){name=1//全局名称始终是字符串控制台.log(fmt(名称))//“1”console.log(`String(${fmt(name)})===${fmt(name){`,String(name)===name)//true}功能测试4(){const名称=1//本地名称控制台.log(fmt(名称))//1console.log(`String(${fmt(name)})==${fmt(name)}`,String(name)==name)//false}测试1();测试2();测试3();测试4()

8
  • var x=新字符串(x);字符串(x)===x返回false。然而({}).toString.call(x).search(/String/)>0总是为棘手的事情而回报 评论 2020年1月3日12:53
  • 1
    函数isClass(x,re){return({}).toString.call(x).search(re)>0;}; isClass(“hello”,/String/)是类(3,/Number/)isClass(null,/null/) 评论 2020年1月3日13:12
  • 这种技巧对我来说似乎“不明显”。聪明的技巧“有效”,但不能清楚地表达意图,我觉得很讨厌。 评论 2021年7月10日22:27
  • 它没有什么聪明的地方。接收相同类型参数的构造函数返回未修改的参数。也许你只是不知道这个财产?另请参见幂等性
    – 木兰
    评论 2021年7月11日16:05
  • 2
    @不同步不明显新字符串(x) 应该不过可以算作字符串。它是一个包装器对象,与普通字符串具有不同的行为。除非您出于某种奇怪的原因对如何处理字符串包装器对象的检查有特定的要求(您可能没有这样的要求,因为根本就没有理由使用它们),否则这并不是对这个答案的反对。 评论 2021年11月26日19:13
14
if(s&&typeofs.valueOf()===“字符串”){//s是字符串}

适用于两种字符串文字让s=‘废话’对于对象字符串let s=新字符串('blah')

1
  • 11
    注意!这将在空字符串上失败,因为这些字符串是虚假的。 评论 2020年3月7日13:15
11

取自洛达什:

函数isString(val){返回类型val==='string'||((!!val&&typeof val=='object')&&object.prototype.toString.call(val)==='[object string]');}console.log(isString('hello world!'));//真实的console.log(isString(新字符串('hello world'));//真实的
1
9

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

var类型=函数(obj){return Object.prototype.toString.apply(obj).replace(/\[对象(.+)\]/i,'$1').toLowerCase();};

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

type('my string')==='string'//truetype(new String('my String'))==='String'//truetype(`my string`)==='string'//truetype(12345)===“字符串”//falsetype({})===“字符串”//false

https://codepen.io/patodiblasi/pen/NQXPwY?编辑器=0012

要检查其他类型:

type(null)//空类型(未定义)//未定义类型([])//数组类型({})//对象type(function(){})//函数类型(123)//编号type(新编号(123))//编号类型(/some_regex/)//regexptype(Symbol(“foo”))//符号
2
  • 2
    这是一个可爱的小功能,尽管我不会亲自使用它,而是根据需要进行特殊类型的检查,比如foo===空typeof foo==“字符串”.否决票可以因为1。这可能有点不合习惯;尽管使用对象.原型.to字符串是很常见的,我从未见过有人像你这样从结果中提取类型,只是与可能结果的精确值进行比较,例如“[对象字符串]”2.您没有解释regex的作用或原因,对于JavaScript新手来说,这可能非常不清楚。目前尚不清楚为什么更喜欢这个答案而不是其他答案。 评论 2021年11月26日18:22
  • 一个荒谬的反例是Object.assign('abc',{[Symbol.toStringTag]:'notAString'})-它是一个字符串,但请尝试将其传递给类型! 评论 2023年5月19日13:53
9

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

设x=“abc”;console.log(x.constructor.name===“String”);//真实的让y=新字符串('abc');console.log(y.constructor.name===“String”);//真实的

性能

在此处输入图像描述

  • 1
    您的解决方案在这里是最好的,也适用于其他对象,如@Orwellophile提供的解决方案。 评论 2022年4月14日9:22
  • 最佳方法。工作比拥有少|条款 评论 2022年10月20日12:38
  • 短一点的话x.constructor===字符串(现在,对于其他类的实例也恰好被命名的情况来说,这也是安全的字符串) 评论 2023年5月19日13:43
6

isString()使用可选链接和最新标准检查传递的参数是否为字符串:

const isString=(值)=>{返回值?。constructor===字符串;}
4

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

if(myVar===myVar+“”){//它的字符串}其他{//是别的东西}

通过在空引号上串联,它将值转换为字符串。如果我的变量已经是字符串,则if语句成功。

7
  • 5
    唯一的问题是,当您想要检查变量的类型时,您是在强制一个变量。与之相比,我觉得这有点贵类型. 评论 2013年9月27日18:29
  • 1
    所以,是的,你是对的。jsperf公司说速度比类型但还是比到字符串。不管怎样,我想我只是喜欢胁迫的语法。 评论 2013年9月30日18:07
  • 5
    这不适用于String类型;var s=新字符串('abc');>s===s+''>假 评论 2017年11月6日22:46
  • 1
    不适用于新字符串创建一种类型的对象.w3schools.com/js/tryit.asp?文件名=tryjs_string_object2 评论 2017年11月7日3:55
  • 2
    我觉得这种做法令人讨厌。编写好的代码并不是为了实现它更短的。关于说出你的意思. 评论 2021年7月10日22:23
4
var a=新字符串('')var b=“”var c=[]函数isString(x){返回x!==空&&x!==未定义&&x.constructor===字符串}console.log(isString(a))console.log(isString(b))console.log(isString(c))
2
  • 如果x.constructor===String也会为null或undefined返回false,为什么需要检查null或undefined? 评论 2018年1月30日2:20
  • 2
    @朱尔斯·曼森:它会抛出错误,而不是产生错误.
    – 莱伊-
    评论 2018年9月22日6:13

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

const is字符串=值=>{尝试{return typeof value()===“字符串”;}捕获(错误){返回false;}};让示例=“你好,世界!”;console.log(is_string(()=>示例));//真实的console.log(is_string(()=>variable_doesnt_exist));//
2
  • -1; 这里的界面很奇怪。从我期望的名字来看是字符串(x)告诉我是否x个是一个字符串,但它告诉我x个是一个可调用的收益字符串。为什么我想传入函数而不是直接传递值? 评论 2021年11月26日19:06
  • @MarkAmery这个是字符串函数用于检查变量是否存在且是否为字符串。传递的箭头函数允许传递一个不存在的变量,而通常,如果变量不存在,我们会收到错误消息:“Uncaught ReferenceError:variable is not defined”。该用例类似于PHP中的错误控制操作符(即。,is_string(@$example)). 这可能不是最好或最常见的做法,但有人可能会发现它很有用,这就是为什么这个答案与众不同的原因。 评论 2021年11月27日2:35

Typechecker助手:

函数isFromType(变量,类型){if(typeof type=='string')res=(typeof variable==type.toLowerCase())else res=(variable.constructor==类型)返回res}

用法:

isFromType('cs','string')//trueisFromType('cs',String)//真isFromType(['cs'],数组)//真isFromType(['cs'],'object')//false

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

(['cs']对象实例//true)

2

这对我来说足够好了。

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

Object.prototype.isString=函数(){return false;};String.prototype.isString=函数(){return true;};var isString=函数(a){return(a!==null)&&(a!=未定义)&&a.isString();};

你可以这样使用。

//返回falseisString(空);isString(void 0);isString(-123);isString(0);isString(true);isString(false);isString([]);isString({});isString(函数(){});isString(0/0);//返回trueisString(“”);isString(新字符串(“ABC”));

警告:在以下情况下,此操作不正确:

//这不是字符串var对象={//但返回真实的lolisString:function(){return true;}}isString(obj)//应为false,但应为true
2

一个简单的解决方案是:

var x=“你好”如果(x===x.toString()){//这是一根绳子}其他{//不是这样的}
5
  • 1
    这不是检查如果它是一根绳子。它会变成一根绳子,很多东西都有toString()功能 评论 2015年5月27日0:13
  • 7
    @MuhammadUmer是的,它将其转换为字符串,然后根据原始值检查身份,该值仅为真的如果原始值也是字符串。 评论 2015年6月1日9:11
  • 5
    这是错误的:你不能盲目地打电话.to字符串任何价值观;如果要检查的x为null或未定义,请尝试,您的代码会引发异常 评论 2017年11月6日20:54
  • 1
    这个想法仍然有用。x===字符串(x)安全有效。 评论 2019年1月25日11:02
  • 真的?这个解决方案对我来说太奇怪了,因为toString()方法可能会被重写并引发异常(由于某些特定的实现),您的检查肯定不会起作用。主要思想是,您不应该调用与您想要获取的内容无关的方法。我甚至没有谈到与到字符串方法。投反对票。 评论 2020年1月28日4:59
2

我将采用另一种方法来处理其余的问题,它试图判断一个变量是一个特定的类型,还是一个特定类型集的成员。
JS建立在鸭子造型上;如果某物像绳子一样嘎嘎作响,我们可以也应该像绳子一样使用它。

7一根绳子?那为什么/\d/.测试(7)工作?
{toString:()=>(“你好”)}一根绳子?那为什么({toString:()=>('hello there')})+'\ngeneral kenobi!'工作?
这些不是关于应该上面的工作,重点是他们做到了。

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

  • 设置类字符串变量
  • 对它和实际字符串运行相同的字符串操作以比较输出(证明它们可以像字符串一样处理)
  • 将类字符串转换为实际字符串以显示给您duckyString()规范需要实数字符串的代码的输入
text=“你好”;out(text.replace(/e/g,'e')+''+'hello there'.replace'(/e/g','e''));out('是字符串?'+duckyString(text)+'\t“'+ducky字符串(text,true)+'”\n“);text=新字符串(‘h my’);out(text.toUpperCase()+''+'oh my'.toUperCase(()));out('是字符串?'+duckyString(text)+'\t“'+ducky字符串(text,true)+'”\n“);文本=368;out((text+'是一个大数字')+“+('368'+'是个大数字’));out('是字符串?'+duckyString(text)+'\t“'+ducky字符串(text,true)+'”\n“);text=['\uD83D','\uDE07'];out(文本[1]。charCodeAt(0)+“+”😇'[1] .charCodeAt(0));out('是字符串?'+duckyString(text)+'\t“'+ducky字符串(text,true)+'”\n“);函数文本(){this.math=7;};Text.protype={toString:function(){return this.math+3+'';}}text=新文本();out(String.prototype.match.call(text,“0”)+“”+text.toString().match(“0””);out('是字符串?'+duckyString(text)+'\t“'+ducky字符串(text,true)+'”\n“);

这与!!x个与…相反x===真并测试是否有数组-喜欢而不需要实际的数组。
jQuery对象;它们是数组吗?没有。它们足够好吗?是的,你可以检查一下阵列原型功能很好。
正是这种灵活性赋予了JS强大的功能和测试能力对于字符串特别降低了代码的互操作性。

上述输出为:

hEllo thErE hEllo thErE是字符串吗?真的“你好”噢我的噢我的是字符串吗?真的“哦,我的”368是一个大数字368是个大数字是字符串吗?真“368”56839 56839是字符串吗?真的”😇"0 0是字符串吗?真“10”

所以,这一切都是关于为什么?你想知道某物是不是字符串。
如果你和我一样,从谷歌来到这里,想看看是否有什么东西串状的,这是一个答案。
它甚至不昂贵,除非您使用的是真正长的或深度嵌套的字符数组。
这是因为它全部是if语句,没有像这样的函数调用.toString().
除非您试图查看一个包含仅包含toString()的或多字节字符,在这种情况下,除了生成字符串外,没有其他方法可以进行检查,并分别计算字节组成的字符数

函数duckyString(字符串,正常,不可接受){var类型=空;if(!不可接受)不可接受={};if(字符串&&!unacceptable.chars&&unacceptanable.to==null)不可接受.to=字符串.toString==数组原型.toString;if(字符串==空);//测试“字符串”是否只是字符串否则,如果(!不可接受.is&&(字符串类型=='string'||string字符串实例))type=“is”;//测试“string+”或“/./”。test(string)`有效否则,如果(!不可接受.to&&string.toString&&typeof string.toString==“函数”&&string.toString!=对象.原型.to字符串)type=“to”;//测试`[…string]`是否有效否则,如果(!不可接受的.chars&&(字符串长度>0 | |字符串长度==0)) {type='chars';//对于每个字符for(var index=0;键入&index<string.length;++索引){var char=字符串[索引];//有效地获得其长度var长度=((duckyString(char,false,{to:true}))?烧焦:duckyString(char,true)||{}).长度;如果(长度==1)继续;//unicode代理pair支持char=duckyString(char,true);length=String.prototype[Symbol&&Symbol.iterator];if(!(length=length&&length.call(char))||length.next().done||!length.next().done)type=null;}}//如果不想自动转换为实际字符串,则返回true或falseif(!(类型&&normalise))//如果他们想知道为什么它是真的,则使用<type>/null返回true或falsy返回(标准化==空)?类型!=null:类型;//执行转换开关(类型){案例“is”:返回字符串;大小写“to”:return string.toString();大小写“chars”:return Array.from(string).join('');}}

包括以下选项

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

这里有更多的测试,因为我是一个完美主义者:

out(“边缘测试”)功能测试(文本、选项){var result=duckyString(文本,false,选项);text=duckyString(text,true,options);out(结果+“+(结果)?”“'+text+'”:文本);}测试(“”);测试(空);测试(未定义);测试(0);测试({长度:0});测试({'0':'!',长度:'1'});测试({});测试(窗口);测试(假);测试([“hi”]);测试(['\uD83D\uDE07']);测试([['1'],2,新字符串(3)]);测试([['1'],2,新字符串(3)],{chars:true});
  • 所有阴性病例似乎都得到了解释
  • 这应该在浏览器>=IE8上运行
  • 支持字符串迭代器的浏览器上支持多字节的字符数组

输出:

边缘卡测试是“”null nullnull null至“0”字符“”字符“!”null null字符“”到“假”null null字符“😇"字符“123”至“1,2,3”
2

从实施洛达什图书馆4.0.0版

//获取标签.jsconst toString=Object.prototype.toString;/***获取“value”的“toStringTag”。**@私人*@param{*}value要查询的值。*@returns{string}返回`toStringTag`。*/函数getTag(值){if(值==空){返回值===未定义? “[对象未定义]”:“[object Null]”;}return toString.call(value);}
//isString.js格式从“./getTag.js”导入getTag;/***检查“value”是否分类为“String”原语或对象。**@自0.1.0起*@类别Lang*@param{*}value要检查的值。*@returns{boolean}如果`value`是字符串,则返回`true`,否则返回`false`。*@示例**isString('abc')*//=>真**isString(1)*//=>假*/函数isString(value){常量类型=值的类型;返回(type===“string”||(type==“object”&&值!=无效&&!Array.isArray(值)&&getTag(value)==“[object String]”));}导出默认值为String;
0
1

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

函数isWhitespaceEmptyString(str){//返回://如果“str”是空字符串、null、未定义或仅由空白组成,则=“true”返回str!(/\S/.test(str)):(str===“”||str===null||str===未定义);}

它还将说明无效的s和未定义类型,它将处理非字符串类型,例如0.

1

我有一个愚蠢的技巧。但很简单。

if(可能是A字符串到UpperCase)weHaveAString(可能是AString)

是的,这远非完美。但是它简单明了。

6
  • @Mike为什么会出错?如果没有“toUpperCase”成员,那么将解析为undefined,这将像预期的那样无法通过条件测试,而不会抛出任何异常。
    – 用户8104581
    评论 2022年6月22日18:31
  • @安德烈克你评论之前有没有试过?将其粘贴到JS控制台中:设x=123;console.log(x.toUpperCase());
    – 迈克
    评论 2022年6月27日16:04
  • @Mike重新阅读答案并检查代码是否匹配。提示:将字符串转换成大写与不同至UpperCase()
    – 用户8104581
    评论 2022年6月28日15:18
  • 1
    @安德烈克啊,你说得对。我读错了。
    – 迈克
    评论 2022年6月28日20:09
  • 1
    太棒了`常量isString=x=>!!x.至UpperCase
    – s3c公司
    评论 2023年3月13日10:13
1

我需要检查变量是否是字符串,并想“快速而脏”地完成它。这是我的方法。因为只有string具有replaceAll方法,所以这是足够的效率。

const isString=(input)=>输入类型?。replaceAll===“函数”//使用示例console.log(isString(true))//对他们俩来说,这都是真的console.log(isString(新字符串('test')))console.log(isString(“测试”))
1
  • 这很简单,很有效。谢谢。 评论 2023年10月23日22:26
0

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

isNaN(“A”)=真;parseInt(“A”)=NaN;isNaN(NaN)=真;

然后我们可以使用isNaN(parseInt())来仅包含字符串

让ignoreNumbers=“ad123a4m”;让ign=ignoreNumbers.split(“”).map((ele)=>isNaN(parseInt(ele?ele:“”).连接(“”);console.log(ign);

0

此函数是检查任何类型的安全方法:

让isType=(值,类型)=>{if(type==null||value==null)返回值===type;return Object.getPrototypeOf(value??{}).constructor===type;}//以下所有工作均符合预期:isType('abc',String);isType(123,数字);isType(/abc/,RegExp);isType(null,null);isType(未定义,未定义);

由此我们可以得出:

让isString=value=>isType(value,String);

//测试此方法:让isType=(值,类型)=>{if(type==null||value==null)返回值===type;return Object.getPrototypeOf(value??{}).constructor===type;}让isString=value=>isType(value,String);let falseCase=[[“null”,null],[“未定义”,未定义],[“对象”,{a:1,b:2}],[“数组”,[1,2,3]],['数字',123],[“零”,0],['RegExp',新RegExp('hello')],[“number with valueOf returning string”,Object.assign(10,{valueOf:()=>“abc”})],['伪装成字符串的对象',{constructor:string}]];让trueCase=[['空文本字符串',''],[“unicode string literal”,string.fromCharCode(10000)],[“空装箱字符串”,新字符串(“”)],[“unicode装箱字符串”,新字符串(string.fromCharCode(10000))],['带覆盖“constructor”的字符串',Object.assign('hi',{constructor:Array})],['string with overrided“toString”',Object.assign('hi',{toString:123})],['带覆盖“valueOf”'的字符串,Object.assign('hi',{valueOf:123})],〔'带覆盖的“构造函数”的字符串',Object.assign('hi',{constructor:RegExp})〕,[“代理字符串”,new Proxy(new string('hello'),{})],];console.log('负面测试:');for(falseCases的let[name,val]){console.log(`Test${name}:\n预期:false\n获得:${isString(val)}`);}console.log('\nPOSITIVE TESTS:');for(let[name,val]of trueCases){console.log(`Test${name}:\n预期:true \n得到:${isString(val)}`);}

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.