[] + [], [] + {}, {} + [], {} + {}

32 阅读3分钟

本质:二元操作符 + 规则

  1. 如果操作数是对象,则对象会转换为原始值
  2. 如果其中一个操作数是字符串的话,另一个操作数也会转换成字符串,进行字符串连接
  3. 否则,两个操作数都将转换成数字或NaN,进行加法操作

对象转为原始数据类型的值的方法

Symbol.ToPrimitive

Symbol.toPrimitive 是 JavaScript 内置对象 Symbol 中的一个 Symbol 值,它用于指定一个对象在进行类型转换时的转换行为。

当我们将一个对象转换为基本类型值时,JavaScript 引擎会调用对象的 valueOf()toString() 方法来尝试获取其原始值。但是有时候我们需要对这种类型转换的行为进行控制,这时候可以在对象上实现 Symbol.toPrimitive 方法。

具体来说,如果一个对象定义了 Symbol.toPrimitive 方法,那么在进行类型转换时,JavaScript 引擎会优先调用该方法来获取对象的原始值,而不是调用 valueOf()toString() 方法。

Symbol.toPrimitive 方法接受一个参数 hint,用于指定转换的目标类型,它可以是以下三个值之一:

  • "number":表示需要将对象转换为数字类型。
  • "string":表示需要将对象转换为字符串类型。
  • "default":表示需要根据上下文来确定转换目标类型。

Symbol.toPrimitive 方法应该返回一个原始值,它表示对象所代表的原始值。如果 Symbol.toPrimitive 方法未被实现,或者返回的值不是原始值类型,则会抛出 TypeError 异常。

需要注意的是,Symbol.toPrimitive 方法是一个符号属性,需要使用 Symbol.toPrimitive 调用该方法。例如,myObj[Symbol.toPrimitive](hint)

Object.prototype.valueOf

Object.prototype.valueOf() 是 JavaScript 内置对象 Object 的原型方法之一。它的作用是返回当前对象的原始值,这个值可以是任何 JavaScript 基本类型(例如字符串、数字、布尔值等)或者是 nullundefined

当我们在某个对象上调用 valueOf() 方法时,JavaScript 引擎会尝试将该对象转换成原始值。如果对象本身已经是原始值类型,那么 valueOf() 方法直接返回该值。否则,它会尝试调用对象的 toString() 方法将其转换成字符串,然后再返回该字符串对应的原始值。

需要注意的是,Object.prototype.valueOf() 方法是一个默认实现,通常情况下应该由派生自 Object 的子类来覆盖该方法以实现更具体的行为。

Object.prototype.toString

Object.prototype.toString() 是 JavaScript 内置对象 Object 的原型方法之一。它的作用是返回一个表示当前对象的字符串。

当我们在某个对象上调用 toString() 方法时,JavaScript 引擎会根据对象的类型不同,返回不同的字符串。具体来说:

  • 对于基本类型值,如字符串、数字、布尔值等,会返回对应的字符串形式。
  • 对于对象类型值,会返回一个形如 "[object Object]" 的字符串,其中 "Object" 表示对象的类型名,可以通过 Object.prototype.toString.call() 来获取。例如,Object.prototype.toString.call([]) 返回的字符串为 "[object Array]",表示该对象是一个数组类型。

需要注意的是,Object.prototype.toString() 方法是一个默认实现,通常情况下应该由派生自 Object 的子类来覆盖该方法以实现更具体的行为。

二元操作符 toNumber

image.png

[] + [], [] + {}, {} + [], {} + {}

如何求原始值

[]的原始值

  1. typeof [][Symbol.ToPrimitive] // undefined
  2. [].valueOf() // []
  3. [].toString() // ''

{}的原始值

  1. typeof {}[Symbol.ToPrimitive] // undefined
  2. {}.valueOf() or ({}).valueOf() // {}
  3. ({}).toString() // '[object Object]'

[] + []

  1. [].toString() + [].toString()
  2. '' + ''
  3. ''

[] + {}

  1. [].toString() + ({}).toString()
  2. '' + '[object Object]'
  3. '[object Object]'

{} + []

  1. {}; + [].toString()
    • ''
  2. 0

{} + {}

其他浏览器控制台:

  1. {}; + {}
    • '[object Object]'
  2. NaN

chrome浏览器控制台:

  1. ({}+{})
  2. '[object Object]'+'[object Object]'
  3. '[object Object][object Object]'