如果表达式是对象,V8会提供一个 ToPrimitve 方法,将其转换为原生数据类型
- 先检测对象中是否存在 valueOf 方法,如果存在并返回了一个原始类型,那么就使用该值进行强制类型转换
- 如果没有 valueOf 方法或 valueOf 方法返回的不是一个原始类型值,则调用对象的 toString() 方法
- 如果 toString() 方法返回一个原始类型值,则使用该值进行强制类型转换
- 如果 valueOf 和 toString 两个方法都不返回基本类型的值,便会触发一个 TypeError 的错误
为什么值为一个空字符串?
[] + [] === ''; // true
- 先调用数组的 valueOf() 方法返回的不是一个原始类型
- 再调用数组的 toString() 方法返回的是一个空字符串
空数组+空对象值为 '[object Object]'
[] + {} === '[object Object]'; // true
- 空对象会先调用原型链上的 value() 方法,返回的不是一个原始类型值
- 空对象会再调用原型链上的 toString() 方法,返回的是一个字符串类型的值 '[object Object]'
为什么会返回0?
{} + [] === 0; // true
- {} 会被认为是一个代码块而不是一个对象
- + 运算符会将空字符串转换成 Number 类型的 0
如何让下面表达式成立?
a == 3 && a == 8 && a == 5
const a = { reg : /\d/g, // 定义一个匹配数字的正则 valueOf() { // 自定义一个valueOf方法来劫持默认的valueOf方法 return this.reg.exec('358')[0]; // 使用正则的exec方法 } } console.log(a == 3 && a == 5 && a == 8); // true
- 在对象中定义一个 valueOf() 方法来劫持原生的 valueOf() 方法
- 定义一个匹配数字的正则
- 使用该正则的 exec() 方法