纯函数给出严格相等的参数,产生非严格相等的结果

时间:2011-08-28 19:58:33

标签: javascript

下面是pure function f f(a) !== f(b)a === b a(注意严格等值),b }和var f = function (x) { return 1 / x; } +0 === -0 // true f(+0) === f(-0) // false

{{1}}

此类功能的存在可能导致难以发现的错误。还有其他我应该厌倦的例子吗?

6 个答案:

答案 0 :(得分:11)

是的,因为NaN !== NaN

var f = function (x) { return Infinity - x; }

Infinity === Infinity // true
f(Infinity) === f(Infinity) // false

f(Infinity) // NaN

其他一些产生NaN的例子,其参数可以严格相等:

0/0
Infinity/Infinity
Infinity*0
Math.sqrt(-1)
Math.log(-1)
Math.asin(-2)

答案 1 :(得分:6)

这种行为完全没问题,因为在数学理论中,-0 === +0是真的,1/(-0) === 1/(+0)不是,因为-inf != +inf

编辑:虽然我真的很惊讶javascript实际上可以处理这些数学概念。

EDIT2:另外,你所描述的现象完全基于这样一个事实:你除以零,你至少应该从中得到一些奇怪的行为。

答案 2 :(得分:2)

1/+0为无穷大且1/-0 - 无效,而+0 === -0。

这可以解释为ECMA将-0定义为等于+0作为特例,而在其他操作中,这两个值保留了它们的不同属性,这导致一些不一致。

这是唯一可能的,因为语言explicitly defines two non-equal values to be equal,实际上并非如此。

其他例子,如果有的话,应该基于同样的人为平等,并且给定http://ecma262-5.com/ELS5_HTML.htm#Section_11.9.6没有其他这样的偏见,所以可能没有其他例子。

如果有任何用处,我们可以通过向0添加-0来确保0不是var f = function(x) { return 1 / (x + 0); } f(+0) === f(-0)

{{1}}

答案 3 :(得分:2)

在ECMAScript 3中,===令人惊讶的另一个例子是连接函数。考虑这样的情况:

function createConstantFunction(result) {
    return function () {
        return result;
    };
}

var oneReturner = createConstantFunction(1);  // a function that always returns 1
var twoReturner = createConstantFunction(2);  // a function that always returns 2

允许实现“加入”两个函数(参见规范的第13.2节),如果它这样做,则oneReturner === twoReturner将是true(参见§13.1.2),即使这两个功能做不同的事情。与此类似:

// a perfect forwarder: returns a sort of "duplicate" of its argument
function duplicateFunction(f) {
    return function (f) {
        return f.apply(this, arguments);
    };
}

var myAlert = duplicateFunction(alert);
console.myLog = duplicateFunction(console.log);

此处的实现可以说是myAlert === console.myLog,即使myAlert实际上等同于alertconsole.myLog实际上等同于console.log

(但ECMAScript 3中没有保留ECMAScript 3的这一方面:不再允许加入函数。)

答案 4 :(得分:0)

我不太确定这是所以可怕;-) Javascript不是纯语言,+ / - 0的存在以及-0和+0的相等是特定于{ {3}}并且“定义明确”,即使有时可能会令人惊讶。 (例如,即使NaN!= NaN始终为真,也很明确。)

来自IEEE-754

  
    

根据IEEE 754标准,负零和正零应与通常(数值)比较运算符相等...

  

从技术上讲,由于f 的两个输入不同,因此结果也可能不同。对于它的价值,Haskell会将0 == -0视为真,但会将(1 / 0) == (1 / (-0))视为错误。

但是,我觉得这是一个有趣的问题。

快乐的编码。

答案 5 :(得分:-1)

有很多这样的功能,这是另一个例子

function f (a) {
  return a + 1;
}

1 ==“1” 但是f(1)!= f(“1”)

这是因为平等是一个细微差别的概念。

或许更可怕的是你的例子-0 === +0。