JavaScript中1+“2“的底层原理

首先,我们知道在许多其它语言中是不支持数字与字符串的相加,其结果会报错。而我们也知道JavaScript在这种情况下会进行隐式类型转换,1+“2”会变成“1”+“2”,最终结果为“12”。
接下来,我们看看其背后的底层原理究竟是什么。
以下面代码为示例:

a+b

V8(chrome的JavaScript引擎)会提供了一个 ToPrimitve 方法,其作用是将 a 和 b 转换为原生数据类型,其转换流程如下:

  • 先检测该对象中是否存在 valueOf 方法,如果有并返回了原始类型,那么就使用该值进行强制类型转换;
  • 如果 valueOf 没有返回原始类型,那么就使用 toString 方法的返回值;
  • 如果 vauleOf 和 toString 两个方法都不返回基本类型值,便会触发一个 TypeError 的错误。

将对象转换为原生类型的流程图如下所示:
在这里插入图片描述
当 V8 执行 1+“2”时,因为这是两个原始值相加,原始值相加的时候,如果其中一项是字符串,那么 V8 会默认将另外一个值也转换为字符串,相当于执行了下面的操作:

Number(1).toString() + "2"

下面再看一组更典型的例子:


var Obj1 = {
    toString() {
      return "200"
    }, 
    valueOf() {
      return 100
    }   
  }
  Obj1+"3"

var Obj2 = {
    toString() {
      return "200"
    }, 
    valueOf() {
      return {}
    }   
  }
  Obj2+"3"

var Obj3 = {
    toString() {
      return {}
    }, 
    valueOf() {
      return {}
    }   
  }
  Obj3+"3"

上面三组案例的结果分别为:

"1003"
"2003"

VM263:9 Uncaught TypeError: Cannot convert object to primitive value
    at <anonymous>:9:6

根据上面的运算查找流程,相信此结果应该一目了然。
简要总结一下,在JavaScript执行加法过程中,V8 会先通过 ToPrimitive 函数,将对象转换为原生的字符串或者是数字类型,在转换过程中,ToPrimitive 会先调用对象的 valueOf 方法,如果没有 valueOf 方法,则调用 toString 方法,如果 vauleOf 和 toString 两个方法都不返回基本类型值,便会触发一个 TypeError 的错误。

猜你喜欢

转载自blog.csdn.net/asd0356/article/details/108522108