参考自 微信公众号 鱼头的Web海洋
关于这道题目:
var a = ?;
if (a == 1 && b == 2 && c == 3) {
console.log('yes');
}
学习了网上的几种解法,如下:
首先,JS中类型转化只有三种情况:
- 转换为布尔值
- 转换为数字
- 转换为字符串
对象在转换类型的时候,会执行原生方法ToPrimitive
其算法如下:
1.如果已经是原始类型,则返回当前值;
2.如果需要转字符串则先调用toString方法,如果此时是原始类型则直接返回,否则再调用valueOf方法并返回结果;
3.如果不是字符串,则先调用valueOf方法,如果此时是原始类型则直接返回,否则再调用toString方法并返回结果;
4.如果都没有原始类型返回,则跑出TypeError类型错误.
解法如下:
1.
var a = {
arr: [3, 2, 1],
valueOf () {
console.group('valueOf');
console.log(this.arr);
console.groupEnd('valueOf');
return this.arr.pop();
}
}
if (a == 1 && a == 2 && a == 3) {
console.log('yes');
}
执行结果:
解析:
1.运行时会先判断 a 的类型,此时typeof a === ‘object’,不是原始类型,也不是字符串,因此会先执行a.valueOf()
2.由于valueOf()被覆盖了,因此执行覆盖后的valueOf(),每一次都会返回a.arr的尾元素,并更新a.arr
3.得出三次执行结果为 1, 2, 3, 实现了这个功能
2.
var b = {
arr: [3, 2, 1],
toString () {
console.group('toString');
console.log(this.arr);
console.groupEnd('toString');
return this.arr.pop();
}
}
if (b == 1 && b == 2 && b == 3) {
console.log('yes');
}
解析:
1.运行时会先判断 b 的类型,此时typeof a === ‘object’,不是原始类型,也不是字符串,因此会先执行b.valueOf()
2.b.valueOf()得到的结果是 {arr: Array(3), toString: ƒ}, 不是原始类型. 不是字符串, 因此执行b.toString()
3.由于toString()被覆盖了,因此执行覆盖后的toString(),每一次都会返回b.arr的尾元素,并更新b.arr
3.得出三次执行结果为 1, 2, 3, 实现了这个功能
3.
var c = {
arr: [3, 2, 1],
[Symbol.toPrimitive] () {
console.group('Symbol.toPrimitive');
console.log(this.arr);
console.group('Symbol.toPrimitive');
return this.arr.pop();
}
}
if (c == 1 && c == 2 && c == 3) {
console.log('yes');
}
解析:
先把上面的方法合并,测试优先级:
var d = {
arr: [3, 2, 1],
valueOf () {
console.group('valueOf');
console.log(this.arr);
console.groupEnd('valueOf');
return this.arr.pop();
},
toString () {
console.group('toString');
console.log(this.arr);
console.groupEnd('toString');
return this.arr.pop();
},
[Symbol.toPrimitive] () {
console.group('Symbol.toPrimitive');
console.log(this.arr);
console.group('Symbol.toPrimitive');
return this.arr.pop();
}
}
if (d == 1 && d == 2 && d == 3) {
console.log('yes');
}
执行结果:
可以看出会先执行toPrimitive这个原生方法,但是被覆盖了,所以执行覆盖后的toPrimitive()
4.
var f = {
reg: /\d/g,
valueOf() { return this.reg.exec(123)[0] }
}
if (f == 1 && f == 2 && f == 3) {
console.log('yes');
}
执行结果:
解析:
1.exec() 方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null。
2.如果匹配成功,exec() 方法返回一个数组,并更新正则表达式对象的属性。返回的数组将完全匹配成功的文本作为第一项,将正则括号里匹配成功的作为数组填充到后面。如果匹配失败,exec() 方法返回 null。
3.先测试 var reg=/\d/g; reg.exec(123);得到以下结果:
可看到正则进行全局搜索,判断返回一个数据,数组的首元素为成功匹配的文本
4.因此每次进行 f == 1, f == 2, f == 3 时都会返回数组的首元素,也就是匹配的文本.由此实现这个功能
参考自 微信公众号 鱼头的Web海洋