【问题标题】:What is the result of adding an Object and an Array in javascript?在javascript中添加对象和数组的结果是什么?
【发布时间】:2011-01-23 09:08:19
【问题描述】:

我在地址栏中尝试了这段代码:

javascript: alert({} + [])

结果是:[object Object]。

javascript: alert(typeof ({} + []))

结果是:字符串。

谁能给我解释一下这是怎么回事?

【问题讨论】:

    标签: javascript types type-conversion


    【解决方案1】:

    连接运算符 (+) 将两个字符串值连接在一起。如果你给它一些不是字符串值的东西,那么它首先调用它们的.toString()方法。

    回应下面的评论,“是的!”

    Object.prototype.toString = function () { return "a"; };
    Array.prototype.toString = function () { return "b"; };
    var foo = {} + [];
    alert(foo); // alerts 'ab'
    

    如果没有对原型进行上述修改,如果您有alert({} + []),那么您将采用{}.toString()(即"[Object object]")和[].toString()(即"",因为数组为空),然后连接他们(仍然是"[Object object]")。这是一个字符串,typeof 会告诉你它是一个字符串。

    【讨论】:

    • 我更改了问题,因为它不会将两者都转换为字符串然后添加它们。无论如何,您似乎是正确的。
    • 所以默认情况下: Object.prototype.toString = function () { return "[object Object]"; }; Array.prototype.toString = function () { return ""; };谢谢,已接受回答。
    • 更像是:Array.prototype.toString = function () { return this.join(','); };
    • @Jacob — 请不要劫持一个答案线程来询问有关另一个问题的问题 — 我已经向您解释了为什么有人可能会否决它。
    【解决方案2】:

    看起来因为+ 运算符未定义为接受参数作为一个[] 和一个{},它基本上将两者都转换为字符串(比尝试将它们转换为数字更有意义)然后应用+ 作为连接运算符。

    编辑: 针对更改后的问题,我认为它们仍然首先被转换为字符串。这是我在 spidermonkey 中尝试过的一个会话:

    js> x=[]+{}
    [object Object]
    js> z=x[0]
    [
    js> x.length
    15
    js> x=[]+{}
    [object Object]
    js> x.length
    15
    js> x[0]
    [
    js> x[1]
    o
    js> for (var i=0;i<x.length;i++) {print(x[i]);}
    [
    o
    b
    j
    e
    c
    t
    
    O
    b
    j
    e
    c
    t
    ]
    js> typeof(x)
    string
    js> print(x)
    [object Object]
    

    发生的事情是{}+[] 的结果是一个字符串,但不是空字符串。而是字符串“[object Object]”。

    【讨论】:

    • 我更改了问题,因为它不会将两者都转换为字符串然后添加它们。
    【解决方案3】:

    这有点复杂。

    你会在这里找到一个很好的解释它是如何工作的:http://www.adequatelygood.com/2010/3/Object-to-Primitive-Conversions-in-JavaScript

    但似乎本樱桃描述的方式确实发生了变化(也是我重新认识的)。如果您将运行他的示例:

    function population(country, pop) {
        return {
            country: country,
            pop: pop,
    
            toString: function () {
                return "[Population " + 
                    "\"" + country + "\" " +
                    pop +
                "]";
            },
    
            valueOf: function () {
                return pop;
            }
        };
    }
    
    var america_pop = population("USA", 350e6);
    var mexico_pop = population("Mexico", 200e6);
    var canada_pop = population("Canada", 200e6);
    
    alert(america_pop); // [Population "USA" 350000000
    
    var north_america_pop = america_pop + mexico_pop + canada_pop;
    
    alert(north_america_pop); // 750000000
    

    这不再是真的,警报将是:
    350000000
    750000000

    alert(obj) 不再调用 valueOf() 而不是 toString(),如果使用 Array.join 则执行

    alert([america_pop]); // [Population "USA" 350000000
    

    已经有一个帖子关于:valueOf() vs. toString() in Javascript

    他们清楚地表明,当 [hint] 是一个数字时总是会调用 valueOf,而且情况总是如此,除非你加入一个数组。这很令人困惑,因为如果你调用 'string' + 'string' 这绝对是一个字符串上下文,但 JS 会首先查看数字上下文,如果它是原始值,则始终调用 valueOf() 方法而不是 toString() /p>

    【讨论】:

      【解决方案4】:

      恐怕比这里解释的要复杂一些。

      问题的标题是:

      在 JavaScript 中添加 Object 和 Array 的结果是什么?

      然后问题询问{}+[] 表达式,这里的每个人都假设它的计算结果为'[object Object]' - 但它总是这样吗?

      立即按 Shift+Control+J 并在 &gt; 提示符处输入 {}+[]

      也许是浏览器的错误?让我们在 Node 中尝试同样的方法:

      这里发生了一些有趣的事情。

      加号 (+) - 实际上被称为 “加法运算符” 而不是 “连接运算符” 就像有人在这里写的那样 - 请参阅 ECMA-262, 6th Edition, Section 12.7.3 - The Addition operator ( + ) - 执行字符串连接数字加法,这对于理解此类示例非常重要。

      曾经有人问过我这样的问题:

      如果alert({}+[]) 显示'[object Object]'x = {}+[] 将'[object Object]' 放入x,那么为什么在控制台或节点REPL 中写入{}+[] 会得到0

      答案是,在对象和数组上使用加号运算符时,会将它们转换为字符串 - 分别为字符串 '[object Object]' 和空字符串 - 这里我们实际上 不是 将对象添加到数组! {} 被解释为一个空块并且评估为空,因此 + 现在被评估为 unary operator[] 数组强制为一个数字,对于一个空数组恰好为零 - 但它不是元素的数量,而是空数组的 0,如果可以,则第一个元素转换为数字,如果不能,则转换为 NaN 用于单元素数组,以及 NaN 用于具有多个元素的任何数组。

      一些更有趣的结果,尝试{}[]+-*/ 运算符的所有组合:

      $ node
      > []+[]
      ''
      > {}+{}
      '[object Object][object Object]'
      > []+{}
      '[object Object]'
      > {}+[]
      0
      > []-[]
      0
      > {}-{}
      NaN
      > []-{}
      NaN
      > {}-[]
      -0
      > []*[]
      0
      > {}*{}
      NaN
      > []*{}
      NaN
      > {}*[]
      ... ^C
      > []/[]
      NaN
      > {}/{}
      NaN
      > []/{}
      NaN
      > {}/[]
      SyntaxError: Invalid regular expression: missing /
          at Object.exports.createScript (vm.js:24:10)
          at REPLServer.defaultEval (repl.js:137:25)
          at bound (domain.js:250:14)
          at REPLServer.runBound [as eval] (domain.js:263:12)
          at REPLServer.<anonymous> (repl.js:392:12)
          at emitOne (events.js:82:20)
          at REPLServer.emit (events.js:169:7)
          at REPLServer.Interface._onLine (readline.js:210:10)
          at REPLServer.Interface._line (readline.js:546:8)
          at REPLServer.Interface._ttyWrite (readline.js:823:14)
      

      这是从内到外学习所有语言怪癖的最佳方法之一。

      【讨论】:

        【解决方案5】:

        基本上会调用toString 方法。您实际上可以通过编写返回数字的toString 方法来覆盖默认行为。

        var obj1 = {
                toString: function () {
                    return 1;
                }
            },
            obj2 = {
                toString: function () {
                    return 2;
                }
        };
        alert(typeof (obj1 + obj2));
        

        【讨论】:

          猜你喜欢
          • 2021-11-27
          • 1970-01-01
          • 1970-01-01
          • 2017-03-29
          • 2019-07-08
          • 2014-05-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多