介绍

昨天在网上看到一道面试题,是关于JavaScript中的+元算符的,如下:

[] + 0 = ?
{} + 0 = ?

要解决这道题,我们首先要了解JavaScript中+运算符的行为,+元算符在JavaScript中主要有三种用途:一是用于数字相加,二是用于字符串连接,三是用于类型转换。

1 + 2 = 3 // 数字相加
'Hello, ' + 'World!' = 'Hello, World!' // 字符串连接
+'1' = 1 // 字符串转换为数字

再回到面试题,可以看出,这并非常规的加法操作,因为运算符两侧的操作数并非都是数字类型,而是包含了数组和对象。难道是字符串连接吗?不确定,是类型转换?好像也不是。

追本溯源,我们先看看MDN上关于+的运行规则吧:

如果+元算符的操作数包含非基本类型(比如对象,数组等),先将其转换为基本类型(primitive type)。

在JavaScript中,基本类型包括undefinednullbooleannumberstringBigIntSymbol

+元算符两侧都是基本类型时,执行规则如下:

  1. 有一个操作数是字符串时,将另一个操作数也转换为字符串,并执行字符串连接;
  2. 有一个操作数是BigInt时,将另一个操作数也转换为BigInt,并执行加法;
  3. 否则,将两个操作数都转换为数字,并执行加法。

举几个列子:

1 + `2` = '12' // 满足规则1,将数字1转换为字符串'1',执行字符串连接
1 + 2n = 3n // 满足规则2,将数字1转换为
null + true = 1 // 满足规则3,将null转换为数字0,将true转换为数字1,执行加法

我们这道题不涉及BigInt,所以只需要关注字符串连接和数字加法就好。

现在来看[] + 0该如何执行,首先[]是数组,不属于基本类型,所以先将它转换为基本类型,对象类型转换为基本类型的操作如下:

  1. 调用对象的toPrimitive方法;
  2. 如果没有toPrimitive方法,则调用valueOf方法;
  3. 如果valueOf方法返回的值不是基本类型,则调用toString方法;
  4. 如果toString方法返回的值仍不是基本类型,则抛出错误。

所以[] + 0的执行过程如下:

  1. []没有toPrimitive方法,所以调用valueOf方法。
  2. valueOf方法返回值仍然是数组对象[]
  3. 接着调用toString方法,返回空字符串''

因此,[] + 0等价于'' + 0, 此时+两侧都是基本类型了,并且满足有一侧是字符串的条件,所以将另一侧的操作数0也转换为字符串,执行字符串连接,结果为'' + '0' = '0'

再来看{} + 0, {}[]一样,都是对象类型,所以先将其转换为基本类型。

  1. {}没有toPrimitive方法,所以调用valueOf方法,返回值仍然是对象{}
  2. 接着调用toString方法,返回字符串'[object Object]'
  3. 然后将'[object Object]'0进行字符串连接,结果为'[object Object]' + '0' = '[object Object]0'

哈哈,但是我要告诉你,这个答案是错误的,这个分析是没有问题的,但是JavaScript解释器不同意,当它看到{}时,会将其解释为一个空的代码块,而不是一个空对象,因此,{} + 实际上等于下面的代码:

{}
+ 0

这时,而{}被视为一个空代码块, 没有返回任何结果,而+ 0被解释为一条独立的语句,返回值是0,最终结果是0

如果要让代码按照我们上面分析的过程执行,那么就要防止JavaScript将{}解释为空代码块,可以用()将其包裹起来。

({}) + 0 // 结果为 '[object Object]0'

总结

[] + 0 = '0'
{} + 0 = 0

说实话这道题目比较偏门,但是对于了解JavaScript中+运算符的行为还是很有帮助的,通过一道题,能了解一个知识点,还是很值得的。

有的时候,不要光纠结问题的答案,更应该关注的是问题背后的原理的规则,就比如这道题,在没有写这篇文章之前,如果让我回答,我是答不上来的,我需要查阅资料,了解+运算符的行为规则,才能得出正确的答案。我觉得相比知道答案,更有意思的是分析的过程,这个过程体现了一个程序员处理问题的逻辑思维能力,小到一道面试题,大到一个复杂的系统设计,都是如此。那么如何培养这种能力呢,我也一直在寻找答案...

今天就到这里了,我们明天见。

今天周六,准备出去逛逛,奈何天气太热,动也不想动,只能呆在家里了。锁凤十代打了两天,手感非常不错,准备留下了,之前买的猛禽就退了吧,现在赚钱不易,还是要精打细算的好。

JavaScript面试题,为什么[] + 0 = '0', 而{} + 0 = 0?的更多相关文章

  1. 如何解决JavaScript中0.1+0.2不等于0.3

    console.log(0.1+0.2===0.3)// true or false?? 在正常的数学逻辑思维中,0.1+0.2=0.3这个逻辑是正确的,但是在JavaScript中0.1+0.2!= ...

  2. 百度地图-省市县联动加载地图 分类: Demo JavaScript 2015-04-26 13:08 530人阅读 评论(0) 收藏

    在平常项目中,我们会遇到这样的业务场景: 客户希望把自己的门店绘制在百度地图上,通过省.市.区的选择,然后加载不同区域下的店铺位置. 先看看效果图吧: 实现思路: 第一步:整理行政区域表: 要实现通过 ...

  3. 深入理解JavaScript系列:为什么03-0.2不等于0.1

    五一宅家看书,所以接着更新一篇文章. 今天讲一下为什么03-0.2不等于0.1这个问题. 有点标题党的味道,在JavaScript中,当你试着对小数进行加减运算时,有时候会发现某个结果并非我们所想的那 ...

  4. jQuery easyUI datagrid 增加求和统计行 分类: JavaScript 2015-01-14 17:46 2178人阅读 评论(0) 收藏

    在datagrid的onLoadSuccess事件增加代码处理. <style type="text/css"> .subtotal { font-weight: bo ...

  5. null的坑 和 比较运算符、相等运算符的隐式转换问题 (在javascript中,null>=0 为真,null<=0 为真,null==0却为假,null到底是什么?)

    null在关系运算中的坑 & 关系运算符的隐式转换问题 注意: 比较运算符 和 相等运算符 的 ECMAscript 语法实现不同. 比较运算符 和 相等运算符 对数据进行了隐式转换, 相当于 ...

  6. 为什么在JavaScript中0.1+0.2不等于0.3?

    0.1+0.2不等于0.3?是不是有点颠覆你的认知,但是,在js中,是真实存在的! console.log(0.1+0.2); // 0.30000000000000004 其实这都是因为浮点数运算的 ...

  7. 为什么js中0.1+0.2不等于0.3,怎样处理使之相等?(转载)

    为什么js中0.1+0.2不等于0.3,怎样处理使之相等? console.log(0.1+0.2===0.3)// true or false?? 在正常的数学逻辑思维中,0.1+0.2=0.3这个 ...

  8. js正则表达式校验非负浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. Zepto,Zepto API 中文版,Zepto 中文手册,Zepto API,Zepto API 中文版,Zepto 中文手册,Zepto API 1.0, Zepto API 1.0 中文版,Zepto 1.0 中文手册,Zepto 1.0 API-translate by yaotaiyang

    Zepto,Zepto API 中文版,Zepto 中文手册,Zepto API,Zepto API 中文版,Zepto 中文手册,Zepto API 1.0, Zepto API 1.0 中文版,Z ...

  10. paip.jdk1.4 1.5(5.0) 1.6(6.0) 7.0 8.0特点比较与不同

    paip.jdk1.4 1.5(5.0)  1.6(6.0) 7.0   8.0特点比较与不同 作者Attilax ,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地 ...

随机推荐

  1. JAVA基础之多线程一期

    一.并发与并行的区别 并发:指同一时间段,两个或多个事件交替进行 并行:指同一时间段,两个或多个事件同时进行 二.进程与线程的区别 进程:正在内存中运行的程序就是进程 线程:线程归属于进程,它是进程中 ...

  2. 一文搞懂Dockerfile

    Dockerfile官网 https://docs.docker.com/reference/dockerfile/ 什么是Dockerfile? Dockerfile 是一个文本文件,其内包含了一条 ...

  3. 雷总小米十周年演讲---国外友人评价第一次看到MIUI系统

    雷总在小米十周年演讲时提到的当时讨论MIUI系统的帖子 xdadevelopers论坛 https://forum.xda-developers.com/showthread.php?t=787877 ...

  4. TVM:Schedule的理解

    schedule与计算逻辑分离是自动代码生成技术的核心概念,由MIT CASIL组的Jonathan Ragan-Kelley在2012年发表在SIGGRAPH上的文章率先提出,然后在2013年发表在 ...

  5. 一个低PE的股票池--选股策略

    EP因子即市盈率因子,常被投资者使用的几个估值因子之一.一般使用PE,即Price to Earning,维基百科上的解释:市盈率指每股市价除以每股收益盈利(Earning Per Share,EPS ...

  6. JVM 使用jstat分析系统的垃圾回收情况

    jstat -gcutil 输出结果分析_助你了解jvm命令,查找JVM堆栈信息,分析性能问题.下面介绍一下jstat命令: jstat:虚拟机统计信息监视工具(JVM Statistics Moni ...

  7. AI面试助手“面试精灵”发布新功能——AI笔试助手

    引言 在职场竞争日益激烈的今天,面试已成为决定职业发展的关键一步.许多专业人士虽然在专业领域拥有深厚的知识,却可能缺乏面试技巧.为了帮助这些专业人士更轻松地获得理想的工作,我们推出了革命性的AI面试助 ...

  8. Linux下搭建Kafka集群

    摘要 Kafka 是一个分布式的基于push-subscribe的消息系统,它具备快速.可扩展.可持久化的特点.由 LinkedIn 开源,用作 LinkedIn 的活动流(Activity Stre ...

  9. 通过chrome插件自动生成博客评论,高效发外链

    最近crazy cattle 3d这个词爆火,很多人都在做,竞争异常激烈,甚至可以说是惨不忍睹. 从最近的数据看,胜出的主要是crazycattle3d.com, crazycattle3d.io, ...

  10. python C3算法

    Python MRO C3算法是python当中计算类继承顺序的一个算法,从python2.3以后就一直使用此算法了. c3 linearization算法称为c3线性化算法 C3算法原理 首先定义几 ...