在JavaScript中检查变量是否为字符串

2735

如何在JavaScript中确定一个变量是字符串还是其他类型?

33个回答

2858

这是对我有效的方法:

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

// Test this approach:

let isString = value => typeof value === 'string' || value instanceof String;

let falseCases = [
  [ 'null', null ],
  [ 'undefined', undefined ],
  [ 'object', { a: 1, b: 2 } ],
  [ 'array', [ 1, 2, 3 ] ],
  [ 'number', 123 ],
  [ 'zero', 0 ],
  [ 'RegExp', new RegExp('hello') ],
  [ 'number with valueOf returning string', Object.assign(10, { valueOf: () => 'abc' }) ],
  [ 'object pretending to be string', { constructor: String } ]
];
let trueCases = [
  [ 'empty literal string', '' ],
  [ 'unicode string literal', String.fromCharCode(10000) ],
  [ 'empty boxed string', new String('') ],
  [ 'unicode boxed string', new String(String.fromCharCode(10000)) ],
  [ 'string with overwritten "constructor"', Object.assign('hi', { constructor: Array }) ],
  [ 'string with overwritten "toString"', Object.assign('hi', { toString: 123 }) ],
  [ 'string with overwritten "valueOf"', Object.assign('hi', { valueOf: 123 }) ],
  [ 'string with overwritten "constructor"', Object.assign('hi', { constructor: RegExp }) ],
  [ 'proxied string', new Proxy(new String('hello'), {}) ],
];

console.log('NEGATIVE TESTS:');
for (let [ name, val ] of falseCases) {
  console.log(`Test ${name}:\n  Expect: false\n  Got:    ${isString(val)}`); 
}

console.log('\nPOSITIVE TESTS:');
for (let [ name, val ] of trueCases) {
  console.log(`Test ${name}:\n  Expect: true\n  Got:    ${isString(val)}`); 
}


159
"myVar instanceof String" 和 "typeof myVar == 'string'" 相比,是否额外做了什么? - svth
122
我记得,在JavaScript中,你可以有字符串类型的变量或String类的对象类型(相同的东西-都是字符串-但定义方式不同),这就是为什么要进行双重检查。 - DRAX
55
var somevar = new String('somestring')console.log(typeof somevar) // object - Danubian Sailor
151
在这里进行instanceof检查是毫无意义的噪音,除非你遵循一些非常不寻常的编码实践。此回答未对其作用或使用原因进行解释,唯一需要它的原因是如果你使用对象封装字符串,但是对象封装字符串是一个毫无价值的功能,没有人使用,Google和Crockford都谴责其为不良实践。(https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml?showone=Wrapper_objects_for_primitive_types#Wrapper_objects_for_primitive_types, http://www.crockford.com/javascript/recommend.html) - Mark Amery
211
我强烈反对认为避免编写正确处理不太可能情况的稳健代码是一种好方法。如果你的代码可能被他人调用,检查 typeofinstanceof 都是明智之举。如果你在问“我刚刚发送了什么 postmessage”,那么 @MarkAmery 的“postmessage”边界情况很重要 - 但你期望它在接口处得到处理,并且不会传播。在其他地方,即使某些 JS 爱好者不赞成这些方法,正确处理非淘汰的编码方法是正确的。除非真正接受字符串,否则永远不要将您的代码注释为接受字符串! - Dewi Morgan
显示剩余38条评论

2387
你可以使用 typeof 运算符:

var booleanValue = true;
var numericalValue = 354;
var stringValue = "This is a String";
var stringObject = new String("This is a String Object");
console.log(typeof booleanValue) // displays "boolean"
console.log(typeof numericalValue) // displays "number"
console.log(typeof stringValue) // displays "string"
console.log(typeof stringObject) // displays "object"

来自此网页的示例(虽然稍作修改)。

对于使用new String()创建的字符串,这种方法不会按预期工作,但这种方法很少使用并且不建议使用[1][2]。如果您需要处理这些字符串,请参阅其他答案中的方法。

// Test this approach:

let isString = value => typeof value === 'string';

let falseCases = [
  [ 'null', null ],
  [ 'undefined', undefined ],
  [ 'object', { a: 1, b: 2 } ],
  [ 'array', [ 1, 2, 3 ] ],
  [ 'number', 123 ],
  [ 'zero', 0 ],
  [ 'RegExp', new RegExp('hello') ],
  [ 'number with valueOf returning string', Object.assign(10, { valueOf: () => 'abc' }) ],
  [ 'object pretending to be string', { constructor: String } ]
];
let trueCases = [
  [ 'empty literal string', '' ],
  [ 'unicode string literal', String.fromCharCode(10000) ],
  [ 'empty boxed string', new String('') ],
  [ 'unicode boxed string', new String(String.fromCharCode(10000)) ],
  [ 'string with overwritten "constructor"', Object.assign('hi', { constructor: Array }) ],
  [ 'string with overwritten "toString"', Object.assign('hi', { toString: 123 }) ],
  [ 'string with overwritten "valueOf"', Object.assign('hi', { valueOf: 123 }) ],
  [ 'string with overwritten "constructor"', Object.assign('hi', { constructor: RegExp }) ],
  [ 'proxied string', new Proxy(new String('hello'), {}) ],
];

console.log('NEGATIVE TESTS:');
for (let [ name, val ] of falseCases) {
  console.log(`Test ${name}:\n  Expect: false\n  Got:    ${isString(val)}`); 
}

console.log('\nPOSITIVE TESTS:');
for (let [ name, val ] of trueCases) {
  console.log(`Test ${name}:\n  Expect: true\n  Got:    ${isString(val)}`); 
}


  1. Google JavaScript编码规范建议永远不要使用基本对象包装器
  2. Douglas Crockford建议废弃基本对象包装器

53
请注意,有些情况下 typeof stringValue 可能会返回 "object" 而不是 "string"。请参阅我的答案评论。 - DRAX
221
我偏爱的答案是使用 typeof 来检测 JavaScript 的数据类型,但有人反对这种方法在处理像 new String('foo') 这样被对象包装的字符串时会出现问题。不过这并不重要,因为被对象包装的字符串是一个毫无价值的功能,你不应该使用它们。Google 的代码风格指南禁止使用它们,Douglas Crockford 建议将它们弃用,而且没有任何库使用它们。假设它们不存在,放心使用 typeof - Mark Amery
8
道格拉斯·克罗克福德是否也建议弃用 typeof?(参考链接:http://www.crockford.com/javascript/recommend.html) - Daniel Le
12
@DanielLe提出了一个替代方案来修复一些问题,而不是因为他原则上反对它。 - Vsevolod Golovanov
6
如果你的代码让你头疼,99.99%的情况下是因为你没有正确地构建代码结构。这不是NaN存在和发挥作用的过错,而是你应该注意、学习并记住,在下次处理可能产生NaN的代码时谨慎对待。 - Mike 'Pomax' Kamermans
显示剩余7条评论

257
function isString(x) {
  return Object.prototype.toString.call(x) === "[object String]"
}

或者,内联(我已经为此设置了UltiSnip):
Object.prototype.toString.call(myVar) === "[object String]"

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

// Test this approach:

function isString(x) {
  return Object.prototype.toString.call(x) === "[object String]"
}

let falseCases = [
  [ 'null', null ],
  [ 'undefined', undefined ],
  [ 'object', { a: 1, b: 2 } ],
  [ 'array', [ 1, 2, 3 ] ],
  [ 'number', 123 ],
  [ 'zero', 0 ],
  [ 'RegExp', new RegExp('hello') ],
  [ 'number with valueOf returning string', Object.assign(10, { valueOf: () => 'abc' }) ],
  [ 'object pretending to be string', { constructor: String } ]
];
let trueCases = [
  [ 'empty literal string', '' ],
  [ 'unicode string literal', String.fromCharCode(10000) ],
  [ 'empty boxed string', new String('') ],
  [ 'unicode boxed string', new String(String.fromCharCode(10000)) ],
  [ 'string with overwritten "constructor"', Object.assign('hi', { constructor: Array }) ],
  [ 'string with overwritten "toString"', Object.assign('hi', { toString: 123 }) ],
  [ 'string with overwritten "valueOf"', Object.assign('hi', { valueOf: 123 }) ],
  [ 'string with overwritten "constructor"', Object.assign('hi', { constructor: RegExp }) ],
  [ 'proxied string', new Proxy(new String('hello'), {}) ],
];

console.log('NEGATIVE TESTS:');
for (let [ name, val ] of falseCases) {
  console.log(`Test ${name}:\n  Expect: false\n  Got:    ${isString(val)}`); 
}

console.log('\nPOSITIVE TESTS:');
for (let [ name, val ] of trueCases) {
  console.log(`Test ${name}:\n  Expect: true\n  Got:    ${isString(val)}`); 
}


22
你推荐使用underscore.js(出于什么奇怪的原因?),但你在这里没有使用它。此外,你用函数污染了全局命名空间。在node.js中,你应该创建一个模块来包含所有这些函数(你可以使用global || window替代window,但这是解决本来不应该存在的问题的一种糟糕方法)。 - Benjamin Gruenbaum
24
我来这里是为了寻找原帖问题的答案,但我不喜欢任何一个回答。所以我查看了underscore做了什么,认为它足够好,可以提取并稍作修改(以避免加载underscore库)。我会澄清我的帖子。 - Orwellophile
35
@Orwellophile,这个回答比DRAX的回答更好在哪里? - Pacerier
7
JS支持代码猴子补丁,因此可以重新定义“Object.prototype”中的“toString”。因此,我会认为依赖于“toString”来检查对象类型,在最好的情况下是一个不良实践。 - Andre Rodrigues
10
我支持将“错误答案”和“散弹式答案”更具体地指向帖子,因为回复数量已经过时,然后在提出更好的答案时解释为什么这些答案是次优的。这是我的意见。 - SmokeRaven
显示剩余19条评论

97

我建议使用 jQuerylodash/Underscore 中的内置函数。它们更简单易用,易于阅读。

任意一个函数都可以处理DRAX所提到的情况......也就是说,它们会检查变量是否为字符串字面量或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()的更多细节。

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


158
这就是JS社区存在问题的本质——检查原始类型只需要一行代码并且涉及基本语言结构,但你建议使用外部库。如果某人已经使用了这些库,那么这可能是一个好主意,但仅仅为了检查类型而下载它们则有点过头了。 - Rafał Wrzeszcz
6
我同意 Rafal 的观点。我到处看到使用这些外部库可以提高“可读性”。如果你懂 JavaScript,那么用它比使用你没用过的外部库更容易理解。_.every() 在开始使用时有点混乱,并且一些简单的函数,例如 _.isBoolean() 已经让我们公司的开发人员感到困惑了。有一个开发者错误地认为,当值为布尔值且为 false 时,该函数会返回 false。对我来说,英语比德语更容易阅读,因为我不懂德语。学习 JavaScript,一切都会变得清晰明了。 - John Harding
22
这些库被广泛使用,并提供了许多有用(且经过测试)的功能。特别是lodash库。我不建议某人仅为解决一个问题而下载该库......但我建议每个JavaScript开发者都下载这个库,看看他们错过了什么。 ;) - ClearCloud8
23
你们所有人都误解了使用类似 Lodash 这样的库的重点:不是速度,也不是“开发便利性”。使用 Lodash 这样的库,原因在于它提供了“防御性”,可以避免导致 JavaScript 应用崩溃的问题。当你试图对对象进行字符串操作(或反之亦然)时,会发生致命错误,而 Lodash 在防止这些错误方面提供了巨大的价值。 - random_user_name
11
所有这些评论都是有道理的,但是仅仅使用JS来建议使用第三方库来“检查类型”,可能会让你在开发房间里被嘲笑。 - MickMalone1983
显示剩余5条评论

64

编辑:目前实现此操作的方法为 typeof value === 'string'。例如:

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

以下内容自 node v4 版本起已弃用。

如果您使用 node.js 环境,可以直接使用 utils 中的内置函数 isString。

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

有替代方案吗? - Anthony Kong
4
文档中写道:“请使用 typeof value === 'string' 替代。” - Mr Rogers
2
x = new String('x'); x.isString(x); 返回 false。虽然有 util.types.isStringObject(),但对于 x = 'x' 类型的字符串它也返回 false。这两个实用函数完全没有任何用处... - spinkus

49

4
我认为这个解决方案是最健壮的,因为它处理了跨框架/跨窗口引用的情况,正如答案中提供的URL所述。 - ewh
1
很好的答案,看起来Underscore.js也使用了这种方法! - Daan
2
@ling 请问一下,为什么您要在 Object.prototype.toString.call(obj) === '[object String]' 周围加上括号? - StubbornShowaGuy
2
那跟 @Orwellophile 的回答有什么不同? - Jonathan H
1
@JonathanH - 如果您查看Orwellophile答案的编辑历史记录,就会发现在撰写答案时,Orwellophile说了一些相当复杂的内容。直到2016年,该答案才被编辑以包含这个内容。因此,Ling应该得到荣誉! - ToolmakerSteve
显示剩余2条评论

39

最佳方法:

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日 记住,您也可以始终使用方法的组合。以下是使用 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

这个函数将使用[自定义]“类型转换” - 更确切地说,“类型/值映射” - 来确定变量是否实际“存在”。现在你可以区分null0!许多时候,您甚至不关心它的类型。规避类型的另一种方法是结合鸭子类型集:
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.prototypeString.prototype都有一个.toString()方法。你只需确保数字的字符串等效性相同,然后确保将其作为Number传递给http函数。换句话说,我们甚至不关心它的类型。
希望这能让你更好地理解 :)

1
你需要其他的检查方式来判断普通数字,因为尝试获取它们的构造函数属性会失败: - user663031
@torazaburo 刚刚在 Chrome 控制台中我成功了。您认为为什么它不能工作? - Mark Amery
2
@torazaburo 你可能想要尝试一下断言((o.constructor === Number || s.constructor === Boolean) )。有趣的是,parseIntNaN是脆弱但功能强大的工具。只需记住,非数字不等于非数字,未定义可以被定义。 - Cody
1
a.constructor === Array 是错误的,有时会失败,请使用 Array.isArray请参见 http://web.mit.edu/jwalden/www/isArray.html - axkibe
1
同意,这并不是完全可靠的。更好的方法是使用属性检查——这是目前唯一真正可靠的方法。例如:if(thing.call) { '它是一个函数'; } 或者 if(thing.defineProperties) { '它是一个对象'; }。感谢您的输入,axkibe! - Cody

38

我真的不明白为什么在这种情况下不直接使用typeof

if (typeof str === 'string') {
  return 42;
}
是的,它不能对包装为对象的字符串(例如new String('foo'))起作用,但这被广泛认为是一种不好的做法,大多数现代开发工具可能会不鼓励使用它们。(如果你看到这样的代码,只需要修复它!) Object.prototype.toString技巧是所有前端开发人员在职业生涯中都曾犯过的错误,但不要被其聪明的外表所迷惑:一旦有东西monkey-patch了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(For What It's Worth);反对某个解决方案,因为它可能会被 monkey-patching Object 原型破坏,这是一个薄弱的论点。在动态语言中,几乎任何事情都可以通过做一些不该做的事情来破坏! - ToolmakerSteve
3
@ToolmakerSteve 很好的观点,你当然是正确的。某人可以轻松地更改所有本机原型,导致一切都无法正常工作。我想我试图表达的是,在一个(JS)世界中,猴子补丁仍然是常见的做法,在依赖这种技术时存在巨大的危险,而当(更简单的)替代方案始终可行时,人们不应该将自己暴露在其中(据我所知,您无法使用猴子补丁来更改typeof)。尽管如此,我已经理解了你的观点。谢谢。 - customcommander
1
这是一个权衡:考虑到两种方法并不总是返回相同的答案。因此,它取决于您的“规格” - 您对字符串的含义。在这种情况下,“充满危险”的说法似乎有点过了。如果有人修改Object.prototype.toString以返回不同的结果...坦白地说,那是他们的问题!在我看来,这种可能性不应成为决定使用哪种方法的因素。(我个人不会费心;我采用您展示的简单方法 - 但我不是编写库代码。) - ToolmakerSteve

32

性能

今天2020.09.17我在MacOS HighSierra 10.13.6上使用Chrome v85、Safari v13.1.2和Firefox v80对选定的解决方案进行测试。

结果

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

  • solutions typeof||instanceof (A, I) and x===x+'' (H) 是快/最快的
  • solution _.isString (lodash lib) 是中等快速
  • solutions B 和 K 是最慢的

enter image description here

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

详细信息

我为以下解决方案执行了2个测试用例

A B C D E F G H I J K L
  • 当变量为字符串时- 可以在这里运行 HERE
  • 当变量不是字符串时 - 可以在这里运行 HERE

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

// https://dev59.com/HW855IYBdhLWcg3w-JQr#9436948
function A(x) {
  return (typeof x == 'string') || (x instanceof String)
}

// https://dev59.com/HW855IYBdhLWcg3w-JQr#17772086
function B(x) {
  return Object.prototype.toString.call(x) === "[object String]"
}

// https://dev59.com/HW855IYBdhLWcg3w-JQr#20958909
function C(x) {
  return _.isString(x);
}

// https://dev59.com/HW855IYBdhLWcg3w-JQr#20958909
function D(x) {
  return $.type(x) === "string";
}

// https://dev59.com/HW855IYBdhLWcg3w-JQr#16215800
function E(x) {
  return x?.constructor === String;
}

// https://stackoverflow.com/a/42493631/860099
function F(x){
  return x?.charAt != null
}


// https://dev59.com/HW855IYBdhLWcg3w-JQr#57443488
function G(x){
  return String(x) === x
}

// https://dev59.com/HW855IYBdhLWcg3w-JQr#19057360
function H(x){
  return x === x + ''
}

// https://dev59.com/HW855IYBdhLWcg3w-JQr#4059166
function I(x) {
  return typeof x == 'string'
}

// https://dev59.com/HW855IYBdhLWcg3w-JQr#28722301
function J(x){
  return x === x?.toString()
}

// https://dev59.com/HW855IYBdhLWcg3w-JQr#58892465
function K(x){
  return x && typeof x.valueOf() === "string"
}

// https://dev59.com/HW855IYBdhLWcg3w-JQr#9436948
function 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的示例结果:

enter image description here


你尝试过多次运行你的测试吗?我对策略“i”在Chrome上运行时x = 123非常怀疑。虽然你在情况A下获得了671M(这本质上是相同的代码,有一个额外的测试),但你只获得了69M。在这里,那个策略在Chrome中赢得了x = 123的胜利。说实话,这并不是很重要,但这只是提醒我们性能微基准测试非常难以做到完美。 - James
是的 - 我过去多次运行测试 - 我现在也在运行 - 你是对的 - 现在我的结果要好得多(我有674M的“i”)- 我会在空闲时间更新它 - 谢谢。 - Kamil Kiełczewski
@jwatkins - 我已经更新了表格并得到了结果 - 感谢您的评论 :) - Kamil Kiełczewski
这非常非常有用 - 谢谢!但是其中一些定时测试可能不正确 - 例如,使用new String("string")创建的字符串,x + '' === x失败。也许它应该限制为正确的测试,或者至少为每个测试结果添加列,以进行简单的测试套件,例如nullundefined123new Object()(应全部返回false),以及"""abc"new String("")new String("abc")(应全部返回true)。 - MikeBeaton
测试A似乎在macOS上的Chrome浏览器中使用==而不是===可以获得轻微的加速效果,但不确定这是否重要。 - MikeBeaton
显示剩余2条评论

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 是运算符。运算符比函数调用快得多。
当性能被测试时,第一个示例比第二个示例慢79%!
查看测试:https://jsperf.com/isstringtype

测试链接已失效,但我相信你。这种信息非常重要。在我看来,这应该是当前领先答案中最受赞的评论,如果不是最受赞的答案。 - Coderer
typeof str === 'string' || str instanceof String(可以在if(..)情况下省略括号); 无论如何,在#2中检查原始类型和对象类型都是清晰且足够的。这些检查应该是“罕见”的。 - user2864740
1
这是一个基准测试,Firefox 上快了 30 倍,2 纳秒对比 50 纳秒。 - milahu
1
是的,@MilaNautikus,“Boolean(str.charCodeAt)”解决方案唯一的问题是它不能处理未定义/空值的情况;否则,我可以只说“const isString = str => str.charCodeAt !== undefined”以获得相同的性能。 - Rob Brander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接