Javascript 纯函数给出严格相等的参数,得到非严格相等的结果

Javascript 纯函数给出严格相等的参数,得到非严格相等的结果,javascript,Javascript,下面是一个f,其中f(a)!=f(b)尽管对于a和b的某些值,a===b(注意严格的等式): var f = function (x) { return 1 / x; } +0 === -0 // true f(+0) === f(-0) // false 这些函数的存在可能导致难以发现bug。还有其他我应该厌倦的例子吗?1/+0是无穷大,1/-0-Infinity,而+0=-0 这可以通过ECMA将-0定义为等于+0这一特殊情况来解释,而在其他操作中,这两个值保留其不同的属性,这会导

下面是一个
f
,其中
f(a)!=f(b)
尽管对于
a
b
的某些值,a===b(注意严格的等式):

var f = function (x) {
   return 1 / x;
}

+0 === -0 // true
f(+0) === f(-0) // false

这些函数的存在可能导致难以发现bug。还有其他我应该厌倦的例子吗?

1/+0
是无穷大,
1/-0
-Infinity,而+0=-0

这可以通过ECMA将-0定义为等于+0这一特殊情况来解释,而在其他操作中,这两个值保留其不同的属性,这会导致一些不一致

这是可能的,因为语言,事实上不是

其他的例子,如果有的话,应该是基于同样的人为平等,并且没有其他这样的例外,所以可能没有其他的例子

如果它有任何用途,我们可以通过向其添加
0
来确保
0
不是
-0

var f = function(x) {
   return 1 / (x + 0);
}
f(+0) === f(-0)

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

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


EDIT2:此外,您描述的现象完全基于这样一个事实,即您被零除,您至少应该从中看到一些奇怪的行为。

有许多这样的函数,下面是另一个例子

function f (a) {
  return a + 1;
}
1==“1” 但是f(1)!=f(“1”)

这是因为平等是一个微妙的概念

也许更可怕的是在你的例子中-0==+0

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

发件人:

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

从技术上讲,由于
f
的两个输入不同,因此结果也可能不同。值得一提的是,Haskell会将
0==-0
视为真,但将
(1/0)==(1/-0))
视为假

然而,我确实发现这是一个有趣的问题


快乐的编码。

是的,因为
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)

在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===tworereturner
也将是
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
实际上等同于
alert
console.myLog


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

我知道这个示例的解释。我对其他示例感兴趣。我可以想到一组函数,其中
f(-0)!=f(+0)
,但imo javascript首先应该将
-0===+0
计算为false。不要认为会有任何例子不是基于
-0===+0
你能“证明”没有其他例子吗?我怎么能?证明必须包含整个javascript语言规范。经验法则<代码>-0==+0由于复杂的数学背景,我不知道如何将它们翻译成可以理解的英语,所以只能计算为真。好了,这是唯一的基地,对于它来说
f(x)!=f(y)
x==y
。这使用
=
运算符。使用
==
操作符可以使其联机。这是编程问题吗?我不确定我是否完全理解这个问题。@Gabe:严格的平等,顾名思义,应该是严格的。我提供的函数表明严格相等实际上没有那么严格,这对我来说确实是个问题。@Random:严格相等只意味着不执行类型转换<代码>-0和
+0
都是数字。你为什么要区分它们呢?无论如何,被零除是没有定义的,其他语言在这种情况下会抛出一个错误。因为属性
a===b
意味着
f(a)==f(b)
对于纯函数
f
是一个很好的选择,你不这样认为吗?一般来说可能。但是在JavaScript中,如果定义
+0!==-0,则这意味着
Math.round(-5/10)!=0
。这可能是一种更普遍的情况,并且会产生更多的问题。你还必须考虑实际的方面,而不仅仅是理论方面的问题。这个例子基本上和我的一样。你有没有一个和我的有点不同的呢?我本来以为问题是为什么f(+0)!=f(-0);我已经更新了答案。考虑到这种违反直觉的情况是由于人工技术声明导致的,
==
运算符在传递两个不同的值-0和+0时必须返回true,如果没有其他类似的异常,那么可能没有其他类似的情况。生成类似于此的其他情况的唯一方法是声明如果传递值1和2,则===运算符返回true。或者两个相等的值是不同的,比如NaN,事实上。你能做出这样的声明吗?!这可能是唯一的办法