大于/小于运算符在Q承诺上的行为与等于运算符不同

Greater/Less than operator behave differently than equal operator on Q promises

本文关键字:运算符 小于 大于 承诺      更新时间:2023-09-26

在使用Javascript承诺时,我遇到了这种奇怪的行为。考虑下面的代码:

var Q = require('q');
var d1 = Q.defer();
var d2 = Q.defer();
compare(d1.promise, d2.promise);
d1.resolve(3);
d2.resolve(3);
function compare(a, b) {
 Q.all([a,b]).then(function(results) {
  console.log('a: ' + a + '   b: ' + b);
  var result =  (a == b)? 1: -1;
  console.log(result);
 });
}

当你运行这段代码时,你得到-1。我意识到,到那时,我没有对传递给匿名函数的结果变量进行评估(我应该这样做)。我的具体问题是:

如果将松散相等(==)操作符更改为大于(>)或小于(<)操作符,并更改传递给resolve()的值,则代码将按预期工作。

所以奇怪的行为是==在承诺方面的行为与<或>。似乎小于(<)和大于(>)在某种程度上具有等待承诺结果的特殊能力,而相等操作符(==,===)则没有。

有人能解释这种行为吗?

在相等的情况下,结果是false,因为您正在比较两个不相同的对象:

从规格:

7.2.12抽象相等比较

…3.如果Type(x)与Type(y)相同,则
   返回执行严格相等比较的结果x === y。

7.2.13严格相等比较

…8. 如果x和y是相同的Object值,返回true。
9. 返回false。


但是,关系比较只定义于字符串和数字。因此JavaScript在比较承诺之前执行类型转换。在这个过程中,它将调用对象的 valueOf 方法,因此它将实际比较a.valueOfb.valueOf的返回值。除此之外,Q覆盖默认的valueOf实现以返回解析后的值:

// XXX deprecated
promise.valueOf = function () {
    if (messages) {
        return promise;
    }
    var nearerValue = nearer(resolvedPromise);
    if (isPromise(nearerValue)) {
        resolvedPromise = nearerValue; // shorten chain
    }
    return nearerValue;
};

但是你可以看到标准库不鼓励这样做,很可能是因为标准承诺没有实现这样的行为。


简化演示:

> var a = {valueOf: function() { return 0; }};
> var b = {valueOf: function() { return 0; }};
> a == b
false
> a >= b
true