看到这样一个问题:{} + [] 的结果是多少? 一脸懵逼..

于是在chrome控制台运行 {} + [] 和用 console.log({} + []) 输出,发现结果不一样..

于是,把各种可能的情况都考虑了一下:

  1. //情形一:控制台直接输出
  2. []+[] //""
  3. []+{} //"[object Object]"
  4. {}+[] //
  5. {}+{} //NaN
  6.  
  7. //情形二:括号语句里面输出
  8. ([]+[]); //""
  9. ([]+{}); //"[object Object]"
  10. ({}+[]); //"[object Object]"
  11. ({}+{}); //"[object Object][object Object]"
  12.  
  13. //情形三:console.log()输出
  14. console.log([]+[]);   //空
  15. console.log([]+{}); //[object Object]
  16. console.log({}+[]);   //[object Object]
  17. console.log({}+{}); //[object Object][object Object]
  18.  
  19. //输出结果长度
  20. console.log(([]+[]).length); //
  21. console.log(([]+{}).length); //
  22. console.log(({}+[]).length); //
  23. console.log(({}+{}).length); //

为什么结果会是这样的呢?被绕晕了。

首先情形二情形三很简单,情形三就是将情形二中得到的字符串通过console.log()指令输出,最后输出的长度就是情形二中求得的 字符串的长度。

现在重点考虑,情形一情形二的区别。

加号运算符———值的类型转换原理

Javascrip基本数据类型UndefinedNullBooleanNumberString,引用数据类型Object类型,其中Object包括array跟function。

加号运算符能执行三种转换:把值转化成基本数据类型,数字和字符串。

  1. //a、b类型不确定
  2. a+b;

(1)如果a 、b都为基本数据类型,直接按基本类型参与运算

(2)如果a或者b是对象类型,首先调用对象的 valueOf 方法,如果返回一个基本类型,则以该基本类型参与运算;否则调用 toString 方法,返回基本类型则参与运算

    一个例外是 Date 的实例,其实例首先调用 toString ,接着才调用 valueOf

(3)否则,抛出错误TypeError

回到最开始的问题

(1)数组与数组相加

  1. []+[] //""
  2.  
  3. [].valueOf(); //[]
  4. [].toString(); //""

数组的 valueOf()方法返回自身,因此不是基本类型,接着调用 toString()方法,空数组返回空字符串。   [1,2].toString(); // "1,2"

(2)数组与对象相加

  1. []+{} //"[object Object]"
  2.  
  3. [].valueOf(); //[]
  4. [].toString(); //""
  5.  
  6. ({}).valueOf(); //object {}
  7. ({}).toString(); //"[object Object]"

对象和数组转换原理一样,普通对象的toString()方法始终返回字符串 “[object Object]”,所以有 “”+ “[object Object]”= “[object Object]”。

(3)对象和数组相加、对象和对象相加

  1. {}+[] //
  2. {}+{} //NaN

发现以上方法在这里行不通了,什么原因呢?

问题在于JavaScript把第一个{},解析成空的代码块并且忽略它了。{}+[] 可以看成 +[]  、{}+{}可以看成+{}。

现在可以明白了,+[] 这里的加号并不是二元元素符的那个加号,而是一元运算符,作用是,把值转换为Number,跟Number()方法一样。

  1. Number([]); //
  2. Number({}); //NaN
  1. //+{} 等价于
  2. Number({})
  3. Number({}.toString()) // {}.valueOf() isn’t primitive
  4. Number("[object Object]")
  5. NaN

为什么第一个{}会被解析成代码块呢?因为这{}在这个声明的起始,所以被当成复合语句块了。

当{}既可以被理解为复合语句块也可以被理解为对象直接量或函数声明的时候,JavaScript将会将其理解成为复合语句块。

然后,怎么修复呢??

问题引到情形二的情况,括号语句里面输出,即强制解析器把它认为是表达式。 js把()中的语句当做一个表达式  JS高程P185

因此{}不能被理解为语句块,而被理解为"[object Object]" + "",console.log("[object Object]"+"")打印结果为[object Object]。

  1. ({}+[]); //"[object Object]"
  2. ({}+{}); //"[object Object][object Object]"

 

参考资料:

JAVASCRIPT中{} + {}的结果是什么?

([] + {}).length ?

{}+[]与console.log({}+[])结果不同?从JavaScript的大括号谈起

JavaScript中[]+[] 、[]+{}、{}+[]、{}+{}的结果分析的更多相关文章

  1. 简单分析JavaScript中的面向对象

    初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...

  2. JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法

    今天在程序中出现一个bugger ,调试了好久,最后才发现,原来是这个问题. 做了一个实验: alert(parseInt("01")),当这个里面的值为01====>07时 ...

  3. javascript中call,apply,bind的用法对比分析

    这篇文章主要给大家对比分析了javascript中call,apply,bind三个函数的用法,非常的详细,这里推荐给小伙伴们.   关于call,apply,bind这三个函数的用法,是学习java ...

  4. C#保留2位小数几种场景总结 游标遍历所有数据库循环执行修改数据库的sql命令 原生js轮盘抽奖实例分析(幸运大转盘抽奖) javascript中的typeof和类型判断

    C#保留2位小数几种场景总结   场景1: C#保留2位小数,.ToString("f2")确实可以,但是如果这个数字本来就小数点后面三位比如1.253,那么转化之后就会变成1.2 ...

  5. Javascript中,实现类与继承的方法和优缺点分析

    Javascript是一种弱类型语言,不存在类的概念,但在js中可以模仿类似于JAVA中的类,实现类与继承 第一种方法:利用Javascript中的原型链 //首先定义一个父类 function An ...

  6. javaScript中with函数用法实例分析

    javaScript 中的 with 函数 ,即所谓的with 语句,可以方便地用来引用某个特定对象中已有的属性,但是不能用来给对象添加属性,要给对象创建新的属性,必须明确地引用该对象. with 函 ...

  7. js实例分析JavaScript中的事件委托和事件绑定

    我们在学习JavaScript中,难免都会去网上查一些资料.也许偶尔就会遇到“事件委托”(也有的称我“事件代理”,这里不评论谁是谁非.以下全部称为“事件委托”),尤其是在查JavaScript的事件处 ...

  8. javascript中基本类型和引用类型的区别分析

    大多数人系统学习过的程序设计语言,在这些语言的学习过程中最早学到的几个要点之一就是值类型和引用类型的区别.下面我们来看一下在 JavaScript 中基本数据类型(Primitive Types)和引 ...

  9. 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型

    前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...

随机推荐

  1. Redis理解和使用

    摘抄并用于自查笔记 1. Redis简介 我们日常Java Web开发,一般使用数据库进行存储,在数据量较大的情况下,单一使用数据库保存数据的系统会因为面向磁盘,磁盘读写速度比较慢而存在严重的性能弊端 ...

  2. naptime

    naptime 有一个长度为n的序列\(a_i\),首尾相接组成了一个环,现在要在这个环上选出若干个区间,使区间长度之和恰好为b,然后忽略区间的顺时针开头元素,权值累加区间中所有的数字,问权值的最大值 ...

  3. Java jmx的使用

    JMX Java Management Extensions,Java管理扩展.本质就是用来监控java语言开发的程序,一般常用于jconsole,java visual VM的监控,今天主要介绍ja ...

  4. UOJ450 复读机

    题意:n个位置,k种颜色.求有多少种方案使得每种颜色恰出现d的倍数次. 解:d=1就快速幂,n,k很小就DP,记得乘组合数来分配位置. d = 2 / 3的时候,考虑生成函数. f(x) = ∑[d ...

  5. duilib教程之duilib入门简明教程1.前言

    关于duilib的介绍就不多讲了,一来不熟,二来小伙伴们想必已经对比了多个界面库,也无需赘述.下面进入正题:    不看广告看疗效! 已有众多知名公司采用duilib做为界面库,如华为网盘.PPS(P ...

  6. SCOI2015

    这周各种头疼,一直睡觉+发呆,啥子都没干. 就补一下之前的东西. d1t1小凸玩矩阵 传送门 一开始脑子抽写了最小费用最大流,不知道自己怎么想的. 第k大最小,明显的二分,又是二分图,二分第k大值,把 ...

  7. VS2010文件包含

    一. 关于iostream.h VS2010的iostream不加.h在后面(加.h的是旧版本),把iostream作为类,正确使用方法: #include<iostream> using ...

  8. mongdb 使用聚合函数异常

    异常信息: Command execution failed:  Error [The 'cursor' option is required, except for aggregate with t ...

  9. CentOS源码安装Wireshark

    (2019年2月19日注:这篇文章原先发在自己github那边的博客,时间是2016年8月25日) Wireshark为网络管理员常用的一个网络管理工具,通过使用这个软件,我们可以对本机网卡上的经过的 ...

  10. HDU--2191 汶川地震购米(多重背包)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2191 分析:有资金n元,而市场有m种大米,每种大米价格不等,重量不等,数量不等, 并且只能整袋购买.如何用 ...