前端杂记让前端飞Web前端之路

关于(a==1&&a==2&&a

2019-05-18  本文已影响6人  会飞小超人

这里考核的其实是非严格相等运算符==的原理,下面是摘自MDN的解释。

相等操作符比较两个值是否相等,在比较前将两个被比较的值转换为相同类型。在转换后(等式的一边或两边都可能被转换),最终的比较方式等同于全等操作符 === 的比较方式。
相等操作符对于不同类型的值,进行的比较如下图所示:


image.png

在上面的表格中,ToNumber(A) 尝试在比较前将参数 A 转换为数字,这与 +A(单目运算符+)的效果相同。ToPrimitive(A)通过尝试调用 A 的A.toString() 和 A.valueOf() 方法,将参数 A 转换为原始值(Primitive)。

结合这道题,B的类型是Number,那么在A==B的比较中,可能存在两种情况的转换:

  1. 如果A类型是StringBoolean,则通过ToNumber()转换,它通过一元正号+(也等同于Number()函数)实现。这种实现是js语言内置的,无法重写。
  2. 如果A类型是Object,则通过toString()valueOf()方法实现。这两个方法是A的方法,是可以重写的。

所以思路就有了,首先确定A是一个对象,然后通过重写A的toString()valueOf()方法来达到目的。

所以代码是:

let a={
  num:1,
  toString(){
    return a.num++
  }
}
a==1&&a==2&&a==3 // true

或者:

let a={
  num:1,
  valueOf(){
    return a.num++
  }
}
a==1&&a==2&&a==3 // true

延伸

稍微修改上面的代码再来两个小测试,就能发现更多有意思的细节:

下面是测试代码:

// valueOf返回Object的情况
let a={
  num:1,
  toString(){
    console.log('toString')
    return a.num++
  },
  valueOf(){
    console.log('valueOf')
    return {num:2}
  }
}
a==1 
// valueOf
// toString
// true
// valueOf返回Boolean的情况
let a={
  num:1,
  toString(){
    console.log('toString')
    return a.num++
  },
  valueOf(){
    console.log('valueOf')
    return true
  }
}
a==1
// valueOf
// true
// valueOf返回String的情况
let a={
  num:1,
  toString(){
    console.log('toString')
    return a.num++
  },
  valueOf(){
    console.log('valueOf')
    return '1'
  }
}
a==1
// valueOf
// true

参考链接:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_sameness
https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/57

上一篇 下一篇

猜你喜欢

热点阅读