ChatGPT解决这个技术问题 Extra ChatGPT

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

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


M
Mark Amery

这对我有用:

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

您可以使用 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
@DanielLe,因为他提出了解决一些问题的替代方案,而不是因为他原则上反对它。
如果它让你头疼,99.99% 的时间是因为你没有正确地构建你的代码。这不是 NaN 存在和做它所做的事情的错,这是您下次使用可能产生它的代码时应该注意、学习并牢记的事情。
Y
Yashwardhan Pauranik

由于 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 来检查对象的类型充其量是一种不好的做法。
我支持“错误答案”和“猎枪式答案”更具体地指帖子,因为回复的数量已经老化,然后还解释为什么这些答案不如你提供更好的答案。我的两分钱。
C
ClearCloud8

我推荐使用 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 的建议才使用第三方库来检查类型不会让你笑出开发室。
D
David

编辑:目前的做法是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。两个实用功能绝对不提供实用功能...
P
Preview
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应该得到荣誉!
C
Community

最好的办法:

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" -- 来确定变量是否真的“存在”。现在您可以在 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。您只需确保数字的等效字符串相同,然后确保将其作为 Number 传递给 http 函数。换句话说,我们甚至不关心它的类型是什么。

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


您需要对普通旧数字进行其他检查,因为尝试获取其构造函数属性将失败:
@torazaburo 刚才在 Chrome 控制台中为我工作得很好。是什么让你认为它行不通?
@torazaburo 您可能想使用断言( (o.constructor === Number || s.constructor === Boolean) )。有趣的是,parseIntNaN 是脆弱但强大的工具。请记住,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!
c
customcommander

老实说,我不明白为什么在这种情况下不简单地使用 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 使其返回不同的结果......坦率地说,这是他们的问题!恕我直言,这种可能性不应成为决定使用哪种方法的因素。 (我个人不打扰;我采用您展示的简单方法 - 但我不是在编写库代码。)
K
Kamil Kiełczewski

表现

今天 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 $.type(x) === "string"; } // https://stackoverflow.com/a/16215800/860099 function E(x) { return x?.constructor === String; } // https://stackoverflow.com/a/42493631/860099 函数 F(x){ return x?.charAt != null } // https://stackoverflow.com/a/57443488/860099 函数 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('不同输入的解决方案结果\n\n'); console.log("'abc' Str '' ' ' '1' '0' 1 0 {} [] true false null undef");让测试 = [ '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` `)}) 这个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 失败。也许它应该仅限于正确的测试,或者至少为每个测试的结果添加列,例如 nullundefined123new Object()(都应该给出 false ) 和 """abc"new String("")new String("abc")(都应该给出 true)。
测试 A 似乎通过使用 == 而不是 === 得到了轻微的加速(至少在 macOS 上的 Chrome 中) - 但不确定这是否重要。
P
Paul Rooney

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

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

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

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 以获得相同的性能
S
ScottyG

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

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

这与 4 年后科迪的回答有何不同?
@Sheljohn Cody 的回答很棒。我的回答(全文)更简短,直截了当。您问... :)
作为一个函数,这需要一种处理 undefinednull 的方法,并且仍然为空字符串(''new String(''))获得正确的答案。
@MikeBeaton 没问题:(mystring || false) && mystring.constructor === String。我使用 false 以防它用于必须返回布尔值的函数。
@MikeBeaton - 空字符串是否会为 .constructor 返回不同的答案?那将是相当令人惊讶的。
w
wheelmaker
if (s && typeof s.valueOf() === "string") {
  // s is a string
}

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


注意力!这将在空字符串上失败,因为它们是错误的。
B
Benj Sicam

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

如果有人想知道来源,那就是github.com/lodash/lodash/blob/master/isString.js
P
Pato

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

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

检查变量是否为字符串:

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

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

要检查其他类型:

type(null) //null
type(undefined) //undefined
type([]) //array
type({}) //object
type(function() {}) //function
type(123) //number
type(new Number(123)) //number
type(/some_regex/) //regexp
type(Symbol("foo")) //symbol

这是一个可爱的小功能,虽然我不会亲自使用它,而宁愿根据需要进行临时类型检查,例如 foo === nulltypeof foo == "string"。否决票可能是因为 1. 这可能有点不习惯;尽管使用 Object.prototype.toString 很常见,但我从未见过有人像您一样将类型从结果中提取出来,只与可能结果的确切值进行比较,例如 "[object String]" 2.您没有解释正则表达式的作用或原因,对于 JavaScript 新手来说,这可能非常不清楚,并且 3. 不清楚为什么更喜欢这个而不是其他答案。
M
Marcel Kohls

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

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

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

表现

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


您的解决方案在这里是最好的,也适用于其他对象,如@Orwellophile 提供的解决方案。
M
Mulan

我发现这种简单的技术对 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) // 断言失败 test(0) / / 断言失败 test(/some regex/) // 断言失败 test([ 5, 6 ]) // 断言失败 test({ a: 1 }) // 断言失败 test(x => x + 1) // 断言失败的

同样的技术也适用于 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") // 断言失败 test(123) test(0) test (/some regex/) // 断言失败 test([ 5, 6 ]) // 断言失败 test({ a: 1 }) // 断言失败 test(x => x + 1) // 断言失败

而对于正则表达式 -

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") // 断言失败 test(123) // 断言失败测试(0) // 断言失败 test(/some regex/) test([ 5, 6 ]) // 断言失败 test({ a: 1 }) // 断言失败 test(x => x + 1) // 断言失败的

对象相同 -

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

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

const test = x => console.assert ( Object(x) === x , `not an object: ${x}` ) test("some string") // 断言失败 test(123) // 断言失败测试(0) // 断言失败 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") // 断言失败 test(123) // 断言失败 test(0 ) // 断言失败 test(/some regex/) // 断言失败 test([ 5, 6 ]) test({ a: 1 }) // 断言失败 test(x => x + 1) // 断言失败

但是,此技术不适用于函数 -

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

var x = new String(x); String(x)===x 返回错误。但是 ({}).toString.call(x).search(/String/)>0 总是返回字符串的东西
function isClass(x,re){return ({}).toString.call(x).search(re)>0;}; isClass("hello",/String/)isClass(3,/Number/)isClass(null,/Null/)
这种技术对我来说似乎“不明显”。聪明的技巧“有效”,但没有清楚地表达意图,我觉得很反感。
没有什么聪明的。接收相同类型参数的构造函数返回未修改的参数。也许你根本不知道这个属性?另请参阅idempotence
@unsynchronized 不过,new String(x) 应该 算作字符串并不明显。它是一个包装对象,具有与普通字符串不同的行为。除非您出于某种奇怪的原因对您希望您的检查如何处理字符串包装器对象有特定要求(您可能没有,因为首先没有理由使用它们),这并不是对这个答案的真正打击.
C
Chris Dolphin

我还发现这也可以正常工作,并且比其他示例要短得多。

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

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


唯一的问题是当你想检查它的类型时你正在强制一个变量。与 typeof 相比,这对我来说似乎有点贵。
所以,是的,你是对的。 jsperf 表示它比 typeof 慢了大约 20%,但仍比 toString 快了不少。无论哪种方式,我想我只是喜欢强制的语法。
这不适用于 String 类型; var s = new String('abc'); > s === s + '' > false
不适用于创建类型 objectnew String cus。 w3schools.com/js/tryit.asp?filename=tryjs_string_object2
我觉得这种方法令人反感。编写好的代码不是为了缩短它。它是关于说出你的意思。
Y
Yin
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))

如果 x.constructor === String 也会为 null 或 undefined 返回 false,为什么需要检查 null 或 undefined?
@JulesManson:它会抛出一个错误,而不是产生 false
G
Grant Miller

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

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

-1;这里的界面很奇怪。从名称中我希望 is_string(x) 告诉我 x 是否是一个字符串,但它告诉我 x 是否是一个可调用的返回一个字符串。为什么我要传入一个函数而不是直接传递我的值?
@MarkAmery 此 is_string 函数用于检查变量是否存在并且是字符串。传递的箭头函数允许传递一个不存在的变量,而通常,如果变量不存在,我们会收到错误:“未捕获的 ReferenceError:变量未定义”。该用例类似于 PHP 中的错误控制运算符(即 is_string(@$example))。这可能不是最佳或最常见的做法,但有人可能会发现它很有用,这就是使这个答案与众不同的原因。
T
Tomozma

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

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

Object.prototype.isString = function() { return false; };
String.prototype.isString = function() { return true; };

var isString = function(a) {
  return (a !== null) && (a !== undefined) && a.isString();
};

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

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

N
Noris

一个简单的解决方案是:

var x = "hello"

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

如果它是一个字符串,这不会检查。它变成一个字符串,很多东西都有toString()功能
@MuhammadUmer 是的,它将其转换为字符串,然后根据原始值检查身份,只有当原始值也是字符串时才会为真。
这是错误的:您不能对任何值盲目地调用 .toString;尝试如果要检查的 x 为 null 或未定义,您的代码会抛出异常
这个想法仍然可用。 x === String(x) 是安全且有效的。
真的吗?这个解决方案对我来说似乎太奇怪了,因为 toString() 方法可能会被覆盖并且可能会抛出异常(由于某些特定的实现),并且您的检查肯定不会起作用。主要思想是你不应该调用与你想要得到的东西无关的方法。我什至没有谈论与 toString 方法相关的不必要的开销。投反对票。
y
yaya

类型检查器助手:

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)


H
Hashbrown

我将在这里采用与其他方法不同的方法,它试图判断一个变量是一个特定的类型,还是一个特定集合的成员。 JS 是建立在鸭式的;如果某些东西像弦一样嘎嘎作响,我们可以而且应该像弦一样使用它。

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

所以我做了一个duckyString() function
在下面我测试了许多其他答案没有解决的案例。对于每个代码:

设置一个类似字符串的变量

对其运行相同的字符串操作和一个真实的字符串来比较输出(证明它们可以像字符串一样对待)

将类似字符串的字符串转换为真实字符串,以向您展示 dadyString() 以规范化需要真实字符串的代码的输入

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"

所以,这就是为什么你想知道某个东西是否是字符串。
如果你像我一样从谷歌来到这里并想看看某些东西是不是类似字符串的 em>,这是一个答案。
除非您使用非常长或深度嵌套的 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 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 上运行

支持字符串迭代器的浏览器支持多字节字符数组

输出:

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"

C
Community

只是为了扩展 @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


Z
ZJR

我有一个愚蠢的技术。但直截了当。

if(maybeAString.toUpperCase)
  weHaveAString(maybeAString)

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


@Mike 为什么会抛出错误?如果没有“toUpperCase”成员,那么它将解析为未定义,这将像预期的那样使条件测试失败,而不会引发任何异常。
@andreyrk 你在评论之前有没有试过?将此粘贴到您的 JS 控制台中:let x = 123; console.log(x.toUpperCase());
@Mike 重新阅读答案并检查您的代码是否匹配。提示:toUpperCasetoUpperCase() 不同
@andreyrk 啊,你是对的。我误读了。
M
Mohamad

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

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

比我们可以使用 isNaN(parseInt()) 只有字符串

让 ignoreNumbers = "ad123a4m";让 ign = ignoreNumbers.split("").map((ele) => isNaN(parseInt(ele)) ? ele : "").join("");控制台.log(ign);


F
Filip Seman

lodashv4.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;

S
Salsabeel

我们也可以使用 isFinite() 而不是 typeof 或 isNAN() 检查这个:

var name="somename",trickyName="123", invalidName="123abc";
typeof name == typeof trickyName == typeof invalidName == "string" 🤷‍♀️

isNAN(name)==true
isNAN(trickyName)==false
isNAN(invalidName)==true 👀

在哪里:

isFinite(name) == false
isFinite(trickyName)== true
isFinite(invalidName)== true

所以我们可以这样做:

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

请注意:

    isFinite("asd123")==false
    isNAN("asd123")==true

A
Aryeh Beitz

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

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

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

对于一些例子:

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

我想我最初是在问如何检查类型,尽管当时我什至不知道如何形成问题。 (我可能只使用 /^\d+$/.test('123') 来避免潜在解析问题的复杂性)