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

问:

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

答1:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

这对我有用:

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

“myVar instanceof String”是否在“typeof myVar == 'string'”之外做任何事情?

@svth 我记得。在 JavaScript 中,您可以拥有可变类型的字符串或对象类型,即字符串类(相同的东西 - 两者都是字符串 - 但定义不同),这就是为什么要双重检查。

var somevar = new String('somestring') console.log(typeof somevar) // 对象

-1 因为这里的 instanceof 检查是毫无意义的噪音,除非您遵循一些非常不寻常的编码实践,而这个答案并不能解释它的作用或您可能使用它的原因。您需要它的唯一原因是如果您使用对象包装的字符串,但对象包装的字符串是没有人使用的毫无价值的功能,Google 和 Crockford 都谴责为不好的做法(google-styleguide.googlecode.com/svn/trunk/…、crockford.com/javascript/recommend.html)。

我强烈反对编写能够正确处理不太可能的情况的可靠代码是应该避免的。如果您的代码可能会被其他人调用,那么同时检查 typeof 和 instanceof 感觉是个不错的建议。 @MarkAmery 的 postmessage 边缘案例很重要,如果您问“我刚刚postmessage做了什么?” - 但是您希望在界面上处理它并且不允许传播。在其他地方,处理未弃用的编码方法似乎是正确的,即使某些 JS 美学不赞成它们。切勿将您的代码评论为接受字符串,除非它确实如此!

答2:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

您可以使用 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]。如果您愿意,请参阅其他答案以了解如何处理这些问题。

Google JavaScript Style Guide 说永远不要使用原始对象包装器。 Douglas Crockford 建议弃用原始对象包装器。

@Wolfy87 请注意,在某些情况下 typeof stringValue 可能会返回“object”而不是“string”。请参阅我的答案的评论。

我的首选答案。反对它的论点是它对于像 new String('foo') 这样的对象包装字符串“失败”,但这并不重要,因为对象包装字符串是一个你不应该使用的毫无价值的功能。 Google 风格指南 forbids them、Douglas Crockford wants them deprecated,没有图书馆使用它们。假装它们不存在,并无所畏惧地使用 typeof。

Douglas Crockford recommend that typeof be deprecated 也没有吗?

@DanielLe,因为他提出了解决一些问题的替代方案,而不是因为他原则上反对它。

如果它让你头疼,99.99% 的时间是因为你没有正确地构建你的代码。这不是 NaN 存在和做它所做的事情的错,这是您下次使用可能产生它的代码时应该注意、学习并牢记的事情。

答3:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

由于 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;
}, {});

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

您推荐 underscore.js(出于什么奇怪的原因?)但您不在这里使用它。此外,你用函数污染了全局命名空间。在 node.js 中,您将创建一个具有所有这些功能的模块(您可以使用 global || window 而不是 window,但这是解决您不应该解决的问题的糟糕方法'首先没有)。

@BenjaminGruenbaum 我来寻找OP问题的答案,但不喜欢任何答案。所以我检查了下划线做了什么,并认为它足够漂亮,可以提取和修改一点(以避免必须加载下划线库)。我会澄清我的帖子。

@Orwellophile,这比 DRAX 的答案好多少?

JS 支持猴子补丁,因此可以在 Object.prototype 中重新定义 toString。因此,我认为依靠 toString 来检查对象的类型充其量是一种不好的做法。

我支持“错误答案”和“猎枪式答案”更具体地指帖子,因为回复的数量已经老化,然后还解释为什么这些答案不如你提供更好的答案。我的两分钱。

答4:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

我推荐使用 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()。

这是 JS 社区问题的本质——检查原始类型是单行的,只涉及语言构造(基本之一),但您建议使用外部库。如果有人已经使用了其中一个库,那可能是个好主意,但仅仅为此下载它们而不是简单地检查类型是一种矫枉过正的做法。

我会同意拉法尔的观点。我到处都看到它提高了使用这些外部库之一的“可读性”。如果您了解 JavaScript,那么它比您未使用的一些外部库更容易阅读。 _.every() 起初使用起来有点令人困惑,而像 _.isBoolean() 这样简单的东西让我公司的开发人员感到困惑。开发人员错误地认为如果该值是布尔值并且是假的,那将是假的。对我来说,英语比德语更容易阅读,因为我不懂德语。学习 JavaScript,一切都会变得有意义。

@RafałWrzeszcz 这些库被广泛使用并提供了很多有用(和测试)的功能。特别是lodash。我不建议有人下载该库仅用于这个解决方案....但我会建议每个 javascript 开发人员下载这个库,看看他们错过了什么。 ;)

你们都错过了像 Lodash 这样的图书馆的意义:不是速度。不是“易于开发”。使用像 Lodash 这样的库的原因提供了“防御性”,以防止会炸毁你的 js 应用程序的问题。当您尝试对对象执行字符串操作时会发生致命错误(反之亦然),Lodash 在防止这些错误方面提供了巨大的价值。

所有这些评论都是有效的,但是,伙计……只有使用 JS 的建议才使用第三方库来检查类型不会让你笑出开发室。

答5:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

编辑:目前的做法是typeof value === ‘string’。例如:

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

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

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

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

有替代品吗?

文档说“改用 typeof value === 'string'”。

x = new String('x'); x.isString(x); 返回 false。有 util.types.isStringObject() 但对于 x = 'x' 类型的字符串返回 false。两个实用功能绝对不提供实用功能...

答6:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

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

我在这里看到了:

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

我认为这个解决方案是最强大的,因为它可以处理答案中提供的 URL 中提到的跨框架/跨窗口参考场景。

很好的答案,看起来 Underscore.js 也使用这种方法!

@ling 只是好奇,为什么要在 Object.prototype.toString.call(obj) === '[object String]' 周围加上括号?

这与@Orwellophile 的回答有何不同?

@JonathanH - 如果您查看 Orwellophile 答案的编辑历史,在撰写此答案时,Orwellophile 说了一些相当复杂的事情。直到 2016 年,该答案才被编辑以包含此内容。所以ling应该得到荣誉!

答7:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

最好的办法:

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 和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。您只需确保数字的等效字符串相同,然后确保将其作为 Number 传递给 http 函数。换句话说,我们甚至不关心它的类型是什么。

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

您需要对普通旧数字进行其他检查,因为尝试获取其构造函数属性将失败:

@torazaburo 刚才在 Chrome 控制台中为我工作得很好。是什么让你认为它行不通?

@torazaburo 您可能想使用断言( (o.constructor === Number || s.constructor === Boolean) )。有趣的是,parseInt 和 NaN 是脆弱但强大的工具。请记住,Not-a-Number 不是 Not-a-Number,并且可以定义 undefined。

a.constructor === Array 是错误的,有时会失败,使用 Array.isArray 见 web.mit.edu/jwalden/www/isArray.html

同意,这不是万无一失的。更好的方法是使用属性检查——这是目前唯一真正的故障安全方法。示例:if(thing.call) { 'its a function'; } 或 if(thing.defineProperties) { 'its an object'; }。感谢您的输入,axkibe!

答8:

huntsbot.com – 高效赚钱,自由工作

老实说,我不明白为什么在这种情况下不简单地使用 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’));

FWIW;反对一个解决方案,因为它可以通过猴子修补对象原型来破坏是一个弱论点。在动态语言中,几乎任何事情都可以通过做你不应该做的事情来破坏!

@ToolmakerSteve Fair。你当然是对的。有人可以很容易地改变所有的原生原型,然后什么都行不通了。我想我想表达的观点是,在猴子修补仍然是常见做法的(JS)世界中,依赖这种技术充满了危险,当(更简单的)替代方案得到保证时,人们不应该将自己暴露在它之下始终工作(AFAIK 你不能猴子补丁 typeof)。尽管如此。谢谢你。

这是一个权衡:,鉴于这两种方法并不总是返回相同的答案。所以这取决于你的“规范”——你所说的字符串是什么意思。 “充满危险” 在这种情况下似乎有点强。如果有人修改 Object.prototype.toString 使其返回不同的结果......坦率地说,这是他们的问题!恕我直言,这种可能性不应成为决定使用哪种方法的因素。 (我个人不打扰;我采用您展示的简单方法 - 但我不是在编写库代码。)

答9:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

表现

今天 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 lib) 中等/快速

解决方案 B 和 K 最慢

https://i.stack.imgur.com/cpaxI.png

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

细节

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

当变量是字符串时 - 你可以在这里运行它

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

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

// https://stackoverflow.com/a/9436948/860099 函数 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 函数 C(x) { return _.isString(x); } // https://stackoverflow.com/a/20958909/860099 函数 D(x) { return KaTeX parse error: Expected 'EOF', got '}' at position 24: … === "string"; }̲ // https://sta…{f.name} + tests.map(v => (1*!!f(v)) ).join `)}) 这个shippet只展示了性能测试中使用的函数——它本身不执行测试!

这是 chrome 的示例结果

https://i.stack.imgur.com/oCOIh.png

您是否尝试过多次运行测试?我非常怀疑策略“i”,在 x = 123 的 Chrome 上运行。你得到 69M,尽管你得到 671M 的案例 A(这基本上是相同的代码,有一个额外的测试)。在这里,该策略在 Chrome 中以 x = 123 获胜。老实说,这并不重要,但只是提醒您,性能微基准测试很难正确执行。

是的 - 我过去多次运行测试 - 我现在也运行它 - 你有 - 现在我的结果好多了(我有 674M 用于“i”) - 我会更新这个(在空闲时间) - 谢谢

@jwatkins - 我用结果更新表格 - 谢谢你的评论:)

这非常非常有用 - 谢谢!但是有些定时测试可能是不正确的——例如,对于使用 new String("string") 创建的字符串,x + '' === x 失败。也许它应该仅限于正确的测试,或者至少为每个测试的结果添加列,例如 null、undefined、123、new Object()(都应该给出 false ) 和 ""、"abc"、new String("")、new String("abc")(都应该给出 true)。

测试 A 似乎通过使用 == 而不是 === 得到了轻微的加速(至少在 macOS 上的 Chrome 中) - 但不确定这是否重要。

答10:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

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

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

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

  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

测试链接死了,但我相信你。这种信息非常重要。恕我直言,这应该是,如果不是最受好评的答案,至少应该是对当前领先答案的最受好评的评论。

typeof str === 'string' || str instanceof String(在 if (..) 情况下可以去掉我喜欢的括号);无论如何,检查#2 中的原始类型和对象类型是清楚且足够的。无论如何,这些检查应该是“罕见的”。

here 是一个基准,在 Firefox 上快 30 倍,2 纳秒 vs 50 纳秒

是的,@MilaNautikus Boolean(str.charCodeAt) 解决方案的唯一问题是它不能处理 undefined/null 的情况;否则我可以只说 const isString = str => str.charCodeAt !== undefined 以获得相同的性能

答11:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

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

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

这与 4 年后科迪的回答有何不同?

@Sheljohn Cody 的回答很棒。我的回答(全文)更简短,直截了当。您问... :)

作为一个函数,这需要一种处理 undefined 和 null 的方法,并且仍然为空字符串('' 和 new String(''))获得正确的答案。

@MikeBeaton 没问题:(mystring || false) && mystring.constructor === String。我使用 false 以防它用于必须返回布尔值的函数。

@MikeBeaton - 空字符串是否会为 .constructor 返回不同的答案?那将是相当令人惊讶的。

原文链接:https://www.huntsbot.com/qa/YlmZ/check-if-a-variable-is-a-string-in-javascript?lang=zh_CN&from=csdn

huntsbot.com – 高效赚钱,自由工作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值