经典面试题 a==1&&a==2&&a==3(简洁版)

48 阅读2分钟

(1)问题

if(a == 1 && a == 2 && a == 3){
    console.log('ok');
}

(2)解答

原理

js 是单线程的,说明这个判断其实是在“不同的时期”运行。

在不同的时期,人可以从小孩成长为大人,再成为老人。

同理,只要让 a 在不同的时期变成不同的值即可。

toString

变量在打印的时候都会调用toString这个方法,js中所有的数据他的原型链顶端都是对象,我们重写他的toString方法就好。

var a = {
    _a: 0,
    toString: () => {
        return ++a._a;
    }
}

测试代码

var a = {
    _a: 0,
    toString: () => {
        return ++a._a;
    }
}

if(a == 1 && a == 2 && a == 3){
    console.log('ok');
}

// ok

(3)思考

直接a = true不行吗

不行,忽略了隐式转换的优先级,等号左边是布偶,右边是数字,会把Boolean转为Number,在进行比较。就变成了都是1==1 && 1==2 && 1==3自然false

(4)扩展

遇上三等号 a===1&&a===2&&a===3

三等号先判断类型,这时候用Object的数据拦截就行,这个函数的意思的定义指定对象中的属性,是一个很强大的自定义功能。

Object.defineProperties(window, {
  _a: {
    value: 0,
    writable: true
  },
  a: {
    get: function() {
      return  ++_a
    }
  }
})

Object.defineProperties 是 JavaScript 中一个用于定义对象属性的方法,它允许你精细控制对象属性的行为,包括读写、枚举、配置和使用特定的 getter 和 setter 函数。

语法如下:

Object.defineProperties(obj, props)

其中:

  • obj:需要被定义属性的对象。
  • props:一个或多个属性描述符对象的集合。每个属性描述符包含以下属性:
    • configurable:是否可以使用 delete 关键字删除该属性,以及是否可以通过属性描述符修改该属性的描述符。默认值为 false
    • enumerable:是否可以在 for...in 循环中枚举该属性。默认值为 false
    • value:属性的默认值。可以是任意的 JavaScript 值。
    • writable:是否可以修改该属性的值。默认为 false
    • get:属性的 getter 函数,当有人尝试访问该属性时,将调用此函数并返回结果。默认值为 undefined
    • set:属性的 setter 函数,当有人尝试设置该属性的值时,将调用此函数并进行操作。默认值为 undefined

例如,下面的代码演示了如何使用 Object.defineProperties 定义一个只读的 x 属性和可读可写的 y 属性:

const obj = {}

Object.defineProperties(obj, {
  'x': {
    value: 100,
    writable: false
  },
  'y': {
    value: 200,
    writable: true
  }
})

console.log(obj.x) // 100
obj.x = 200 // 报错,因为 x 属性是只读的
console.log(obj.y) // 200
obj.y = 300
console.log(obj.y) // 300

总之,Object.defineProperties 方法是 JavaScript 中定义对象属性的一种强大方式,可以让你极大地控制属性的行为,并可以实现一些高级的特性,如 getter 和 setter 函数。

结束~ 参考文章