logo

相等,还是不等(4)

Last Updated: 2023-02-24

入门。

在连续对多个相等条件进行判断的时候,可以用and(&&),or(||)来连接,但并不是所有的条件都会被检查,比如&&在遇到第一个False的时候,无论后面的真假,可以直接返回False;同样的||在遇到第一个True的时候整个语句的真假已定。

放弃?

这个坑源自这篇文章:什么时候a==1 && a==2 && a==3?

var aᅠ = 1;
var a = 2;
var ᅠa = 3;
if (aᅠ == 1 && a == 2 && ᅠa == 3) {
  console.log('Whaaaaa?');
}

进阶!

方法 1

谜底揭开的时候,我的第一感觉是,这好无聊...实际上三个a并不是同一个变量,这里用到了一个不可见的韩语的 Unicode 字符U+FFA0,叫做 Halfwidth Hangul Filler,第一个变量是a后面加上那个字符,而第三个是a之前加上那个字符,由于不可见,所以看起来好像是同一个a。可以把它转换为十六进制看看:

> "ᅠa".charCodeAt(0).toString(16)
'ffa0'

正是U+FFA0

方法 2

另一种方法满足a==1 && a==2 && a==3而不需要不可见字符:

let n = 1;
let a = {valueOf() {return n++;}}
console.log(a == 1 && a == 2 && a == 3) // => true

在 JavaScript 中,任何一个 object 都有valueOf()这个方法(类似于toString()),这个 object 在计算中会用valueOf()来产生一个值:

> b = {valueOf: () => 10}
{ valueOf: [Function: valueOf] }

直接打印出 b 并不会看到 10:

> b
{ valueOf: [Function: valueOf] }

但放在计算中则会现原形:

> b == 10
true
> b == 1
false
> b + 20
30

方法 3

方法 2 如果用===则返回的是false

console.log(a === 1 && a === 2 && a === 3); // => false

因为虽然计算 b 的值的时候返回的是 10,它的类型依然是 object:

> typeof(b)
'object'

这是一种满足===的方法:

let i = 0;
Object.defineProperty(global, 'a', {
  get: function () {
    return ++i;
  },
});
console.log(a === 1 && a === 2 && a === 3); // => true

如果不是在 node 而是在浏览器中运行需要将global换成window。这两个特殊的全局 object 的 property 可以直接使用。而且作为 property,a的类型跟它的返回值相同为number

> typeof(a)
'number'