[译] 在JS中,如何让(a===1 && a===2 && a === 3)(严格相等)的值为true?

栏目: JavaScript · 发布时间: 7年前

内容简介:我们先简单了解这道JS经典问题, 然后再解决它的扩展问题。内容概览:如果你已经了解过这个问题并且知道如何解决这个JS谜题(是的,只是一个谜题,我并不想在生产代码中看到这样的用例) , 那你可以直接跳到下一节,阅读它的扩展问题。关于这个问题在reddit上有相关讨论, 下面是我看到最有趣的评论

我们先简单了解这道JS经典问题, 然后再解决它的扩展问题。

内容概览:

  • 重温(a==1&&a==2&&a==3)(宽松相等)问题
    • (a==1&&a==2&&a==3)问题描述
  • (a===1&&a===2&&a===3)扩展问题

如果你已经了解过这个问题并且知道如何解决这个JS谜题(是的,只是一个谜题,我并不想在生产代码中看到这样的用例) , 那你可以直接跳到下一节,阅读它的扩展问题。关于这个问题在reddit上有相关讨论, 下面是我看到最有趣的评论

"如果我在代码库中看到这样的代码,我可能就很绝望了" // 译者注: 谁看到都会很绝望吧

(a ==1 && a==2 && a==3) 的值可以是true吗?

回答是肯定的, 具体可以看下面的代码

const a = { value : 0 };
a.valueOf = function() {
    return this.value += 1;
};

console.log(a==1 && a==2 && a==3); //true
复制代码

通常, 在面试中问这类问题的目的并不是要求面试者记住这样的答案,而是想要了解面试者在面对这道题目时,是如何思考的以及他们是否有了解过Javascript中关于 == 的奇特的语法特性。

秘密就在于"宽松相等操作符 == "

在JS中,宽松相等 == 会先将左右两两边的值转化成相同的原始类型,然后再去比较他们是否相等。在转化之后( == 一边或两边都需要转化),最后的相等匹配会像 === 符号一样去执行判断。宽松相等是可逆的,对于任何值A与B,通常 A == BB == A 具有相同的表现(除了转换的顺序不同)。可以在这里详细深度地了解宽松匹配 == 与严格匹配 ===

Javascript会如何强制转换这个值呢?

在进行两个值的比较时,执行了类型的强制转换, 让我们先了解下内置的转换函数。

ToPrimitive(input, PreferredType?)
复制代码

可选参数 PreferredType 可以指定最终转化的类型,它可以是 Number 类型或 String 类型,这依赖于 ToPrimitive() 方法执行的结果返回的是 Number 类型或 String 类型。

值的转化过程如下

TypeError

如果 PreferredTypeNumber , 那转换算法就会像上述说明的顺序执行,如果是 String ,步骤2和步骤3会交换顺序。 PreferredType 是一个缺省值,如果不输入的话, Date 类型会被当作 String 类型处理,其他变量会当作 Number 处理。默认的 valueOf 返回 this ,默认的toString()会返回类型信息。

如上是操作符 +== 调用 toPrimitive() 的执行过程。

所以在上面的代码中, 如JS引擎所解析的, a == 11 是基本类型, JS引擎会尝试将 a 转换成 Number 类型,然后在上面的算法中, a.valueOf 被调用并且返回1(自增1并且返回自己)。在 a==2a==3 发生了同样的类型转换并增加自己的值。

(a === 1 && a === 2 && a ===3)的值也能是true吗?

当然也可以, 具体请看下面的代码

var value = 0; //window.value
Object.defineProperty(window, 'a', {
    get: function() {
        return this.value += 1;
    }
});

console.log(a===1 && a===2 && a===3) // true
复制代码

从经典问题的解答中,我们了解到JS中的原始类型将不再满足于上面的条件(严格相等没有转化的过程),所以我们需要通过一些方式去调用一个函数,并在这个函数中做我们想做的事情。但是执行函数往往需要在函数名字后引入 () 。并且由于这里不是宽松相等 ==valueOf 将不会被JS引擎调用。Emmm, 有点棘手。还好有 Property 函数, 特别是 getter 描述符, 带来了解决这个问题的办法。

属性描述符有两种类型, 数据描述符和存取描述符。

  1. 数据描述符

    强制键值 - value

    可选键值

    - configurable
     - enumable
     - writeable
    复制代码

    例子

    {
        value: 5,
        writable: true
    }
    复制代码
  2. 存取描述符

    强制键值 - get/set或都设定 可选键值 - confiturable - enumerable 例子

    {
        get: function () { return 5; },
        enumerable: true
    }
    复制代码

MDN上关于存取描述符的例子

// Example of an object property added
    // with defineProperty with an accessor property descriptor

    var bValue = 38;

    Object.defineProperty(o, 'b', {
        // Using shorthand method names (ES2015 feature).
        // This is equivalent to:
        // get: function() { return bValue; },
        // set: function(newValue) { bValue = newValue; },
        get() { return bValue; },
        set(newValue) { bValue = newValue; },
        enumerable: true,
        configurable: true
    });
    o.b; // 38
    // 'b' property exists in the o object and its value is 38
    // The value of o.b is now always identical to bValue,
    // unless o.b is redefined
复制代码

在问题的解决方案中, 我们使用 Object.defineProperty 为对象定义了一个属性。你可以在这里深入了解 Object.defineProperty 的语法与定义。 有趣的是, getset 是可以通过 "."操作符 调用的方法, 举个例子, a 有一个具有 getterb 属性, 它可以像对象的其他属性一样去调用,类似于 a.b 。这可以解决我们最初的问题, 我们需要调用一个无需 () 的函数, 通过 get 属性, 我们可以调用一个函数并且不用在函数名后添加 ()

在上面提到的解决方案中, 我们在window对象上定义了一个具有getter的 a 属性, 所以 a 可以在代码中直接被访问到(全局变量), 因此也可以直接获得a的值。如果我们在其他对象上定义了属性 a 而不是window的话,例如object1, 我们就需要改变题目为 object1.a===1 && object1.a===2 && object1.a===3 了。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Probability and Computing: Randomization and Probabilistic Techn

Probability and Computing: Randomization and Probabilistic Techn

Michael Mitzenmacher、Eli Upfal / Cambridge University Press / 2017-7-3 / USD 62.23

Greatly expanded, this new edition requires only an elementary background in discrete mathematics and offers a comprehensive introduction to the role of randomization and probabilistic techniques in m......一起来看看 《Probability and Computing: Randomization and Probabilistic Techn》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具