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


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


1178
2017-10-30 14:36


起源


回顾四年后的这种情况令人羞愧,但又有点畏缩。有愚蠢的问题,但没关系。问这种事情是我学习的唯一方法:D - Olical
@Olical我不会觉得那么糟糕,截至今天,超过518人投票给出了一个不太正确的答案,而851人发现 一个 正确答案。你创建了可能是规范定义的东西 确定变量是否为字符串 在Javascript社区。不幸的是,SO社区为你的优秀问题提供了如此糟糕的答案。 :) - Orwellophile
@Orwellophile现在我们已经六年了。如果它们可用,我仍然使用typeof或lodash的类型检查方法。在我职业生涯的任何一点上,我都没有接受过接受的答案。它可能不是“完美”,但它的工作:) - Olical
@Olical我从下划线(lodash)得到了答案,所以我不能高度评价这个选项。但是,既然你提到职业生涯,如果我正在面试你,我可能不会注意到你是否曾经使用过 typeof, 但是我 将 如果你使用过,请注意(并给予适当的印象) toString.call(x) === "[object String]" - Orwellophile
我这么做多年了,我还是忘了:/ - Captain Hypertext


答案:


您可以使用 typeof 运营商:

var booleanValue = true; 
var numericalValue = 354;
var stringValue = "This is a String";
alert(typeof booleanValue) // displays "boolean"
alert(typeof numericalValue) // displays "number"
alert(typeof stringValue) // displays "string"

例子来自 这个网页。 (虽然稍微修改了例子)。


1103
2017-10-30 14:40



@ Wolfy87请注意,在某些情况下,typeof stringValue可能会返回“object”而不是“string”。请参阅我的回答评论。 - DRAX
我的首选答案。反对它的论点是,对于包含对象的字符串,它“失败” new String('foo'),但这并不重要,因为对象包装的字符串是一个你不应该使用的毫无价值的功能。 Google风格指南 禁止他们,道格拉斯克罗克福德 希望他们弃用,没有图书馆使用它们。假装他们不存在,并使用 typeof 没有恐惧。 - Mark Amery
没有 Douglas Crockford建议这样做 typeof 被弃用 还有? - Daniel Le
@DanielLe,因为他提出了一个解决一些问题的替代品,而不是因为他原则上反对它。 - Vsevolod Golovanov
@VsevolodGolovanov你怎么知道他原则上不反对它?我所知道的只是那些问题正是他为什么建议当前实施的 typeof 被弃用。 - Daniel Le


这对我有用:

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

1462
2018-02-24 19:38



“myVar instanceof String”是否做了“typeof myVar =='string'”之外的任何事情? - svth
@svth我记得。在JavaScript中,你可以有变量类型的字符串或对象类型,它是String类(同样的东西 - 都是字符串 - 但定义不同),这就是为什么要进行双重检查。 - DRAX
var somevar = new String('somestring')console.log(typeof somevar)// object - Danubian Sailor
-1因为 instanceof 检查这里是无意义的噪音,除非你跟随一些 很不寻常 编码实践,这个答案没有解释它的作用或为什么你可以使用它。您需要它的唯一原因是如果您使用对象包装的字符串,但对象包装的字符串是一个没有人使用的毫无价值的功能,Google和Crockford都谴责这是不好的做法(google-styleguide.googlecode.com/svn/trunk/..., crockford.com/javascript/recommend.html)。 - Mark Amery
我强烈反对,编写正确处理不太可能的案例的可靠代码是值得避免的。检查两者 typeof 和 instanceof 如果您的代码可能被其他人调用,那么感觉就像是一个好建议。 @ MarkAmery的 postmessage 边缘情况很重要,如果你问“我刚才是什么 postmessaged?“ - 但你希望在界面上处理并且不允许传播。在其他地方,即使某些JS审美者不同意它们,处理非弃用的编码方法似乎也是正确的。永远不要将你的代码注释为接受字符串,除非确实如此! - Dewi Morgan


由于有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/下划线)。 免责声明:我为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;
}, {});

101
2017-07-21 11:59



你推荐使用underscore.js(出于什么奇怪的原因?)但你不在这里使用它。此外,您使用函数污染全局命名空间。在node.js中,您将创建一个具有所有这些功能的模块(您 能够 使用 global || window 代替 window 但这对解决你不应该首先遇到的问题来说是一个糟糕的方法。 - Benjamin Gruenbaum
@BenjaminGruenbaum我来寻找OP问题的答案,并不喜欢任何答案。所以我检查了下划线做了什么,并认为它足以提取和修改一点(以避免必须加载下划线库)。我会澄清我的帖子。 - Orwellophile
@Orwellophile很酷,我现在明白了,你的原始答案就像你建议强调自己一样。就个人而言,我只是检查一下 myObject+"" === myObject 检查一个对象是否是一个字符串(甚至更好,我不会首先在行为驱动型系统中键入检查)。 - Benjamin Gruenbaum
针对系统架构问题的人们提供的酷解决方案。 - Ihsan
@Orwellophile, 这比DRAX的答案更好吗? - Pacerier


我建议使用内置函数 jQuery的 要么 lodash /下划线。它们使用起来更简单,更易于阅读。

这两个函数都将处理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 _.isString()的文档 更多细节。

看到 $ .type()的jQuery文档 更多细节。


78
2018-01-06 20:43



这是JS社区出现问题的必要条件 - 对原始类型的检查是一个单行并且只涉及语言构造(基本的一个),但是您建议使用外部库。如果某人已经使用了这些库中的一个,那么这可能是一个好主意,但仅仅为此而下载而不是简单地检查类型是一种过度杀伤力。 - Rafał Wrzeszcz
我要同意拉法尔。我到处都看到它提高了使用这些外部库之一的“可读性”。如果您了解JavaScript,那么比您未使用的外部库更容易阅读。 _.every() 起初使用起来有点令人困惑,而且很简单 _.isBoolean() 我的公司混淆了开发人员。如果值是布尔值并且为假,则开发人员错误地认为它将是错误的。对我来说,英语比德语更容易阅读,因为我不懂德语。学习JavaScript,这一切都有意义。 - John Harding
@RafałWrzeszcz这些库使用相当广泛,并提供了许多有用(和测试)的功能。特别是lodash。我不建议有人下载该库只用于这个解决方案....但我会建议每个javascript开发人员下载这个库,看看他们错过了什么。 ;) - ClearCloud8
所有你们都错过了像Lodash这样的图书馆:不是速度。不是“易于开发”。 原因 使用像Lodash这样的图书馆提供“防御性”来解决会破坏你的js app的问题。当您尝试对对象执行字符串操作时(或反之亦然)会发生致命错误,并且Lodash在防止这些错误方面提供了巨大的价值。 - cale_b
请记住,许多人将在Node或类似Node的环境中执行此操作,很少有人会在那里使用jQuery。 - Matt Fletcher


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

我在这看到:

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


28
2017-07-24 19:07



我认为这个解决方案是最强大的,因为它处理跨框架/跨窗口参考场景,如答案中提供的URL中所述。 - ewh
很好的答案,看起来像Underscore.js也使用这种方法! - Daan
@ling只是好奇,你为什么要括号括起来 Object.prototype.toString.call(obj) === '[object String]'? - StubbornShowaGuy
@StubbornShowaGuy,我想这是代码可读性。 - Earlee
@Earlee你的意思是 (x === y) 具有更好的可读性 x === y? - StubbornShowaGuy


您可以使用此开源可重用 is-string组件 检查var是否是字符串,同时避免复制粘贴它。

例子:

 isString(3) // => false
 isString('') // => true

另外,这是如何 isString 在AngularJS中实现:

function isString(value) {return typeof value === 'string';}

23
2018-02-10 13:10



如何改善DRAX的答案? - Sheljohn


最好的办法:

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

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

希望这可以帮助。

编辑; 2016年12月5日

请记住,您也可以始终使用方法组合。这是一个使用的例子 内联地图 与...的行动 类型

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” - 来确定变量是否实际“存在”。现在你可以分开那些讨厌的头发 null0

多次 你甚至不关心它的类型。避免打字的另一种方法是组合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。换句话说,我们甚至没有 关心 它的类型是什么。

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


15
2018-04-25 13:15



您需要对普通旧数字进行其他检查,因为尝试获取其构造函数属性将失败:
@torazaburo刚刚在Chrome控制台中为我工作得很好。是什么让你觉得它不起作用? - Mark Amery
@torazaburo你可能想玩断言( (o.constructor === Number || s.constructor === Boolean) )。有趣的是, parseInt 和 NaN 是脆弱但功能强大的工具。请记住,Not-a-Number不是非数字,可以定义未定义。 - Cody
a.constructor ===数组错误,有时会失败,请使用Array.isArray看看 web.mit.edu/jwalden/www/isArray.html - axkibe
同意,这不是故障安全的。更好的方法是使用属性检查 - 这是目前唯一真正的故障安全方式。例: if(thing.call) { 'its a function'; } 要么 if(thing.defineProperties) { 'its an object'; }。感谢您的投入,axkibe! - Cody


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

7
2017-09-06 05:06