全面分析toString与valueOf,并随手解决掉几道大厂必备面试题( 二 )

Nice.
valueOf

返回当前对象的原始值 。
具体功能与toString大同小异 , 同样具有以上的自动调用和重写方法 。
这里就没什么好说的了 , 主要为两者间的区别 , 有请继续往下看????
let c = [1, 2, 3]let d = {a:2}console.log(c.valueOf())// [1, 2, 3]console.log(d.valueOf())// {a:2}复制代码两者区别
  • 共同点:在输出对象时会自动调用 。
  • 不同点:默认返回值不同 , 且存在优先级关系 。
二者并存的情况下 , 在数值运算中 , 优先调用了valueOf , 字符串运算中 , 优先调用了toString
看代码方可知晓:
class A {valueOf() {return 2}toString() {return '哈哈哈'}}let a = new A()console.log(String(a))// '哈哈哈'=> (toString)console.log(Number(a))// 2=> (valueOf)console.log(a + '22')// '222'=> (valueOf)console.log(a == 2)// true=> (valueOf)console.log(a === 2)// false=> (严格等于不会触发隐式转换)复制代码结果给人的感觉是 , 如果转换为字符串时调用toString方法 , 如果是转换为数值时则调用valueOf方法 。
但其中的 a + '22' 很不和谐 , 字符串合拼应该是调用toString方法 。为了追究真相 , 我们需要更严谨的实验 。
  • 暂且先把 valueOf 方法去掉
class A {toString() {return '哈哈哈'}}let a = new A()console.log(String(a))// '哈哈哈'=> (toString)console.log(Number(a))// NaN=> (toString)console.log(a + '22')// '哈哈哈22'=> (toString)console.log(a == 2)// false=> (toString)复制代码
  • 去掉 toString 方法看看
class A {valueOf() {return 2}}let a = new A()console.log(String(a))// '[object Object]'=> (toString)console.log(Number(a))// 2=> (valueOf)console.log(a + '22')// '222'=> (valueOf)console.log(a == 2)// true=> (valueOf)复制代码发现有点不同吧?!它没有像上面 toString 那样统一规整 。对于那个 [object Object] , 我估计是从 Object 那里继承过来的 , 我们再去掉它看看 。
class A {valueOf() {return 2}}let a = new A()Object.prototype.toString = null; console.log(String(a))// 2=> (valueOf)console.log(Number(a))// 2=> (valueOf)console.log(a + '22')// '222'=> (valueOf)console.log(a == 2)// true=> (valueOf)复制代码总结:valueOf偏向于运算 , toString偏向于显示 。
  1. 在进行对象转换时 , 将优先调用toString方法 , 如若没有重写 toString , 将调用 valueOf 方法;如果两个方法都没有重写 , 则按ObjecttoString输出 。
  2. 在进行强转字符串类型时 , 将优先调用 toString 方法 , 强转为数字时优先调用 valueOf
  3. 使用运算操作符的情况下 , valueOf的优先级高于toString
[Symbol.toPrimitive]
MDN:Symbol.toPrimitive 是一个内置的 Symbol 值 , 它是作为对象的函数值属性存在的 , 当一个对象转换为对应的原始值时 , 会调用此函数 。
是不是有点懵??? 把它当做一个函数就行了~~