V8 是怎么执行加法操作的?

  1. 把第一个表达式 (AdditiveExpression) 的值赋值给左引用 (lref)。
  2. 使用 GetValue(lref) 获取左引用 (lref) 的计算结果,并赋值给左值。
  3. 使用 ReturnIfAbrupt(lval) 如果报错就返回错误。
  4. 把第二个表达式 (MultiplicativeExpression) 的值赋值给右引用 (rref)。
  5. 使用 GetValue(rref) 获取右引用 (rref) 的计算结果,并赋值给 rval。
  6. 使用 ReturnIfAbrupt(rval) 如果报错就返回错误。
  7. 使用 ToPrimitive(lval) 获取左值 (lval) 的计算结果,并将其赋值给左原生值 (lprim)。
  8. 使用 ToPrimitive(rval) 获取右值 (rval) 的计算结果,并将其赋值给右原生值 (rprim)。
  9. 如果 Type(lprim) 和 Type(rprim) 中有一个是 String,则:
    • 把 ToString(lprim) 的结果赋给左字符串 (lstr);
    • 把 ToString(rprim) 的结果赋给右字符串 (rstr);
    • 返回左字符串 (lstr) 和右字符串 (rstr) 拼接的字符串。
  10. 把 ToNumber(lprim) 的结果赋给左数字 (lnum)。
  11. 把 ToNumber(rprim) 的结果赋给右数字 (rnum)。
  12. 返回左数字 (lnum) 和右数字 (rnum) 相加的数值。

通俗地理解,V8 会提供了一个 ToPrimitve 方法,其作用是将 a 和 b 转换为原生数据类型,其转换流程如下:

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

在执行加法操作的时候,V8 会通过 ToPrimitve 方法将对象类型转换为原生类型,最后就是两个原生类型相加,

  • 如果其中一个值的类型是字符串时,则另一个值也需要强制转换为字符串,然后做字符串的连接运算。
  • 在其他情况时,所有的值都会转换为数字类型值,然后做数字的相加。