a === 0 的同时能满足 a === 1 吗?

148 阅读2分钟

起因

之前冲浪的时候看到一道题目,问能不能实现这种情况:

    a === 0 && a === 1 // true

当时第一时间我的反应是 怎么可能!

之后我仔细想了一下,其实应该是有操作空间的。

思路

  • getter

get语法将对象属性绑定到查询该属性时将被调用的函数。

    let obj = {
      name: 'zebra',
      get names(){
        return obj.name;
      }
    };

    console.log(obj, obj.name, obj.names); // { name: 'zebra', names: [Getter] } zebra zebra

我还能行.jpg

那按照这个说法,我直接改呢?

let obj = {
  staticProp: 0,
  get ages(){
    return ++obj.staticProp;
  }
};

console.log(obj.ages === 1 && obj.ages === 2); // true

ohh.jpg

怎么感觉希望就在前方啊!!!

我直接A了出来~

let obj = {
  staticProp: -1,
  get ages(){
    return ++obj.staticProp;
  }
};

let a = obj.ages;

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

???.jpg

这不合理啊?为啥啊?

let obj = {
  staticProp: -1,
  get ages(){
    return ++obj.staticProp;
  }
};

let a = obj.ages;

console.log(a,a,a,a); // 0 0 0 0
console.log(obj.ages, obj.ages); // 1 2
console.log(a,a,a,a); // 0 0 0 0

这。。。

我再试试?

// ...rest

a += 100;
console.log(typeof obj.ages);  // number
console.log(a,a,a,a);  // 100 100 100 100
console.log(obj.ages, obj.ages); // 1 2
console.log(a,a,a,a); // 100 100 100 100

好家伙, 我终于破案了,直接指向导致obj.ages直接被保存在一个原始类型的数值中,这导致读取a的时候,根本就不进obj.agesgetter

顶不住了.jpg

裂开了。 G!

Proxy

之前在整理ES6新功能的时候,我记得好像看过Proxy.

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

不BB, 我们看一个简单的例子。

var obj = new Proxy({}, {
  get: function (target, key, receiver) {
    console.log(`getting ${key}!`);
    return Reflect.get(target, key, receiver);
  },
  set: function (target, key, value, receiver) {
    console.log(`setting ${key}!`);
    return Reflect.set(target, key, value, receiver);
  }
});
obj.value = 1;
console.log('apple');
console.log(obj);
console.log('pineapple');
console.log(obj.value);
//  results --> 
//    setting value!
//    apple
//    { value: 1 }
//    pineapple
//    getting value!
//    1

看上去好像有get那味了,我试试看:

    const obj = new Proxy({}, {
      get: function (target, key, receiver) {
        console.log(`getting ${key}!`);
        // return Reflect.get(target, key, receiver);
        return ++target[key];
      },
      set: function (target, key, value, receiver) {
        console.log(`setting ${key}!`);
        return Reflect.set(target, key, value, receiver);
      }
    });
    obj.value = 0;
    console.log(obj.value === 1 && obj.value === 2); // true

和之前的结果相似。

难不成.jpg

但是也不行。

a === 0 的时候就已经固定了a是基础类型了,根本没办法改,所以尝试使用 === 来的都不行。(不信你试试~)

a == 0 && a == 1

但如果是==的话, 我们就有操作空间了。 在这里给大家复习一下:

相等操作符比较两个值是否相等,在比较前将两个被比较的值转换为相同类型。在转换后(等式的一边或两边都可能被转换),最终的比较方式等同于全等操作符 === 的比较方式。 相等操作符满足交换律。

所以下面这种操作也是可以的:

const obj = {
  value: 1,
  toString(){
    return obj.value
  }
};

console.log(obj == 1) // true

那解决方案就很简单了:

const obj = {
  value: 0,
  toString(){
    return ++obj.value
  }
};

console.log(obj == 1 && obj == 2) // true

撒花.jpg

结论

a == 0 && a == 1 行!

a === 0 && a === 1 不行!

以上。