【问题标题】:Check if a variable is a string in JavaScript检查变量是否是 JavaScript 中的字符串
【发布时间】:2011-05-02 19:54:18
【问题描述】:

如何判断一个变量是字符串还是 JavaScript 中的其他东西?

【问题讨论】:

    标签: javascript string


    【解决方案1】:

    这对我有用:

    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) // object
    • -1 因为这里的instanceof 检查是毫无意义的噪音,除非您遵循一些非常不寻常的编码实践,而这个答案并不能解释它的作用或原因你可能会使用它。您需要它的唯一原因是如果您使用对象包装的字符串,但对象包装的字符串是没有人使用的毫无价值的功能,Google 和 Crockford 都谴责为不好的做法(google-styleguide.googlecode.com/svn/trunk/…crockford.com/javascript/recommend.html)。
    • 我强烈反对编写能够正确处理不太可能的情况的可靠代码是应该避免的。检查typeofinstanceof 如果您的代码可能被其他人调用,感觉就像是一个好建议。 @MarkAmery 的 postmessage 边缘情况很重要,如果你问“我刚刚postmessaged 是什么?” - 但是您希望在界面上处理它并且不允许传播。在其他地方,处理未弃用的编码方法似乎是正确的,即使一些 JS 美学不赞成它们。切勿将您的代码注释为接受字符串,除非它确实如此!
    【解决方案2】:

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


    1. Google JavaScript 样式指南says to never use primitive object wrappers
    2. 道格拉斯·克罗克福德recommended that primitive object wrappers be deprecated

    【讨论】:

    • @Wolfy87 请注意,在某些情况下 typeof stringValue 可能返回“object”而不是“string”。请参阅我的答案中的 cmets。
    • 我的首选答案。反对它的论点是它对于像new String('foo') 这样的对象包装字符串“失败”,但这并不重要,因为对象包装字符串是一个你不应该使用的毫无价值的功能。 Google 风格指南 forbids them、Douglas Crockford wants them deprecated,没有图书馆使用它们。假装它们不存在,并无所畏惧地使用typeof
    • @DanielLe,因为他提出了一个可以解决一些问题的替代方案,而不是因为他原则上反对它。
    • 如果它让您头疼,99.99% 的时间是因为您没有正确构建代码。这不是 NaN 存在和做它所做的事情的错,这是你下次使用可能产生它的代码时应该注意、学习并牢记的事情。
    【解决方案3】:

    由于 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】:

    我推荐使用 jQuerylodash/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 社区问题的本质——检查原始类型是单行的,只涉及语言构造(基础之一),但您建议使用外部库。如果有人已经使用了其中一个库,那可能是个好主意,但仅仅为此下载它们而不是简单地检查类型就有点过头了。
    • 我同意 Rafal 的观点。我到处都看到它提高了使用这些外部库之一的“可读性”。如果您了解 JavaScript,那么它比您未使用的一些外部库更容易阅读。 _.every() 起初使用起来有点令人困惑,像 _.isBoolean() 这样简单的东西让我公司的开发人员感到困惑。开发人员错误地认为如果该值是布尔值并且为假,那将是假的。对我来说,英语比德语更容易阅读,因为我不懂德语。学习 JavaScript,一切都会有意义。
    • @RafałWrzeszcz 这些库被广泛使用并提供了很多有用(和测试)的功能。特别是lodash。我不建议有人下载该库仅用于这个解决方案....但我会建议每个 javascript 开发人员下载这个库,看看他们错过了什么。 ;)
    • 你们都错过了像 Lodash 这样的库的要点:不是速度。不是“易于开发”。 原因 使用像 Lodash 这样的库提供了“防御性”,以防止会炸毁您的 js 应用程序的问题。当您尝试对对象执行字符串操作时会发生致命错误(反之亦然),而 Lodash 在防止这些错误方面提供了巨大的价值。
    • 所有这些 cmets 都是有效的,但是,伙计......只有 JS 才会建议使用第三方库来检查类型不会让你笑开发室。
    【解决方案5】:
    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 答案的编辑历史,在编写 this 答案时,Orwellophile 说了一些相当复杂的事情。仅在 2016 年,该答案才被编辑以包含此内容。所以 ling 应该得到荣誉!
    【解决方案6】:

    最好的方法:

    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 日

    请记住,您也可以随时使用多种方法的组合。下面是一个使用 typeofinline map 动作示例:

    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.isArray 见web.mit.edu/jwalden/www/isArray.html
    • 同意,这不是故障安全的。更好的方法是使用属性检查——这是目前唯一真正安全的方法。示例:if(thing.call) { 'its a function'; }if(thing.defineProperties) { 'its an object'; }。感谢您的投入,axkibe!
    【解决方案7】:

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

    编辑:目前的做法是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。两个完全不提供任何实用程序的实用程序函数...
    【解决方案9】:

    性能

    今天 2020 年 9 月 17 日,我在 Chrome v85、Safari v13.1.2 和 Firefox v80 上对 MacOs HighSierra 10.13.6 执行所选解决方案的测试。

    结果

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

    • 解决方案 typeof||instanceof (A, I) 和 x===x+'' (H) 最快/最快
    • 解决方案 _.isString(lodash 库)中等/快速
    • 解决方案 B 和 K 最慢

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

    详情

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

    • 当变量是字符串时 - 你可以运行它HERE
    • 当变量不是字符串时 - 你可以运行它HERE

    下面的 sn-p 给出了解决方案之间的差异

    // https://stackoverflow.com/a/9436948/860099
    function 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
    function C(x) {
      return _.isString(x);
    }
    
    // https://stackoverflow.com/a/20958909/860099
    function 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
    function F(x){
      return x?.charAt != null
    }
    
    
    // https://stackoverflow.com/a/57443488/860099
    function 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('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 的示例结果

    【讨论】:

    • 您是否尝试过多次运行测试?我强烈怀疑策略“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")(都应该给@987654)。跨度>
    • 使用 == 而不是 ===,测试 A 似乎得到了轻微的加速(至少在 macOS 上的 Chrome 中)——但不确定这是否重要。
    【解决方案10】:

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

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

    例如,如果我想编写一个函数来测试某个内容是否为字符串,我可以通过以下两种方式之一来实现:

    1) const isString = str =&gt; (Object.prototype.toString.call(str) === '[object String]');

    2)const isString = str =&gt; ((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 =&gt; str.charCodeAt !== undefined 以获得相同的性能
    【解决方案11】:

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

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

    【讨论】:

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

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

    【讨论】:

    • 注意!这将在空字符串上失败,因为它们是错误的。
    【解决方案13】:

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

    【讨论】:

    【解决方案14】:

    你可以使用这个函数来确定任何东西的类型:

    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. 不清楚为什么更喜欢这个而不是其他答案。
    【解决方案15】:

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

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

    对于 RegExp -

    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") // assertion failed
    test(123)           // assertion failed
    test(0)             // assertion failed
    test(/some regex/)  
    test([ 5, 6 ])      // assertion failed
    test({ a: 1 })      // assertion failed
    test(x => x + 1)    // assertion failed

    对象也一样-

    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") // assertion failed
    test(123)           // assertion failed
    test(0)             // assertion failed
    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") // assertion failed
    test(123)           // assertion failed
    test(0)             // assertion failed
    test(/some regex/)  // assertion failed
    test([ 5, 6 ])      
    test({ a: 1 })      // assertion failed
    test(x => x + 1)    // assertion failed

    这种技术适用于函数但是 -

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

    【讨论】:

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

    我还发现这也很好用,而且它比其他示例短很多。

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

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

    【讨论】:

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

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

    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))。这可能不是最佳或最常见的做法,但有人可能会觉得它很有用,这就是这个答案与众不同的原因。
    【解决方案19】:

    这对我来说已经足够了。

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

    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
    

    【讨论】:

      【解决方案20】:

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

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

      性能

      【讨论】:

        【解决方案21】:

        一个简单的解决方案是:

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

        【讨论】:

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

        类型检查器助手:

        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)

        【讨论】:

          【解决方案23】:

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

          7 是字符串吗?那为什么/\d/.test(7) 有效?
          {toString:()=&gt;('hello there')} 是字符串吗?那为什么({toString:()=&gt;('hello there')}) + '\ngeneral kenobi!' 有效?
          这些不是关于应该上述工作的问题,重点是他们做到了。

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

          • 设置类似字符串的变量
          • 对其运行相同的字符串操作和一个真实的字符串来比较输出(证明它们可以被视为字符串)
          • 将类似字符串的字符串转换为真实字符串,以向您展示 duckyString() 以规范化需要真实字符串的代码的输入
          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');
          

          这与 !!xx===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"
          

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

          【讨论】:

            【解决方案24】:

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

            它还将考虑nulls 和undefined 类型,它会处理非字符串类型,例如0

            【讨论】:

              【解决方案25】:

              只有字符串没有数字的代码

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

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

              let ignoreNumbers = "ad123a4m";
              
              let ign = ignoreNumbers.split("").map((ele) => isNaN(parseInt(ele)) ? ele : "").join("");
              
              console.log(ign);

              【讨论】:

                【解决方案26】:

                lodash库实现v4.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;
                

                【讨论】:

                  【解决方案27】:

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

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

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

                  还有一些例子:

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

                  【讨论】:

                  • 我想我最初是在问如何检查类型,虽然当时我什至不知道如何形成问题。 (我可能只是使用/^\d+$/.test('123') 来避免潜在解析问题的复杂性)
                  猜你喜欢
                  • 2011-12-06
                  • 2020-07-24
                  • 1970-01-01
                  • 2016-10-18
                  • 2017-10-30
                  相关资源
                  最近更新 更多