聊聊JS中的ToPrimitive原始值转换方法

2,101 阅读3分钟

下面4句的结果是什么,以及为什么?

[] + {}

{} + []

{} + {}

[] + []

结果:"[object Object]"   0  "[object Object][object Object]"   ""

JS中+运算规则

  • (1)正号:将其他类型强制转换为数字类型

  • (2)加法运算: 加法运算又分为两种,数字相加的二元运算和字符串连接运算

加法运算的规则

  将加号两边都转换为原始数据类型。如果其中有一个转换结果为string类型,使用ToString强制
转换另一个运算元,然后做字符串拼接操作;否则就是都使用ToNumber强制转换为数字作加法运算。

类型转换

  在进行类型转换的时候会进行ToPrimitive运算,该运算的逻辑如下:

ToPrimitive(input, PreferredType)

input是调用的对象,PreferredType是期望返回的结果类型
  • a:判断input是否是对象,如果不是直接return input

  • b:根据PreferredType定义hint,hint的取值一共有三种情况:'default'(PreferredType为空), 'number'(PreferredType是number), 'string'(PreferredType是string)

  • c:判断该对象是否有Symbol.toPrimitive方法, 如果有则传入参数hint进行调用,若执行结果是基本类型,则return该结果,否则抛出TypeError。

  • d:如果hint是'default',则改为'number'。也就是说默认是按'number'。除了Date对象,和Symbol对象。Date对象转换时hint参数是String。Symbol对象进行类型转换会抛出异常。

  • e: 执行OrdinaryToPrimitive运算

    如果hint是'string',调用toString方法,得到的是原始数据类型,返回该值;否则调用valueOf方法,如果得到的是原始数据类型,返回该值;否则抛出异常

    如果hint是'number',则相反;先调用valueOf方法,得到的是原始数据类型,返回该值;否则调用toString方法,如果得到的是原始数据类型,返回该值;否则抛出异常

js中加法操作,参数PreferredType一般是Default

+正号操作,参数PreferredType一般是Number

valueOf与toString方法的返回值

  • (1)对于Object

    valueOf:返回对象本身

    toString:返回的是"[object type]"字符串,"type"指的是对象本身的类型识别。例如Object对象返回"[object Object]",Math对象返回"[object Math]"

  • (2)对于Array

    valueOf:返回对象本身

    toString方法返回值: 相当于用数组值调用join(',')所返回的字符串。例如:[1,2,3].toString()会是"1,2,3"

  • (3)对于Number

    valueOf:返回对象本身

    toString:转换为字符串类型时的字符串值。可以传一个参数,决定转换为字符串时的进制(2、8、16)

  • (4)对于String

    valueOf:返回对象本身

    toString:返回对象本身

  • (4)对于Boolean

    valueOf:返回对象本身

    toString:返回"true"或"false"字符串

[] + {}

[]先调用valueOf()返回的是本身,继续调用toString方法,返回"",{}调用valueOf返回本身,调用toString方法,返回"[object Object]", 所以"" + "[object Object]",进行字符串拼接操作。打印结果为"[object Object]"

{} + []

{}有两种常见的用途(1)对象的定义(2)区块语句。这里的{}会被浏览器认为是区块语句而不是对象字面量,所以{} + [] 相当于 +[],相当于把[]强制转换成数字,转换结果为0。打印结果为0

{} + {}

{}调用valueOf返回本身,调用toString方法,返回"[object Object]", 所以"[object Object]" + "[object Object]",进行字符串拼接操作。打印结果为"[object Object][object Object]"。火狐浏览器除外,火狐浏览器会把第一个{}当作区块语句,相当于+{},转化为+"[object Object]",转为数字结果为NaN。

[] + []

[]先调用valueOf()返回的是本身,继续调用toString方法,返回""。相当于"" + ""。打印结果为""