作为一名专业的数学家,我在Javscript的相同性运算符 ==
(也称为“抽象比较”,“松散相等性”)中看到了尝试在实体之间建立等价关系的尝试,包括反身,对称和传递。不幸的是,这三个基本属性中的两个失败了:
A == A
可能是错误的,例如
NaN == NaN // false
A == B
并且B == C
一起并不暗示A == C
,例如
'1' == 1 // true
1 == '01' // true
'1' == '01' // false
只有对称属性可以生存:
A == B
暗示B == A
,在任何情况下哪种侵犯都可能是无法想象的,并且会导致严重的叛乱;)
为什么等价关系很重要?
因为那是最重要,最普遍的关系类型,因此得到众多示例和应用程序的支持。最重要的应用是将实体分解为等价类,这本身就是理解关系的一种非常方便和直观的方式。不能等同就导致缺少等同类,这又导致缺乏直观性和众所周知的不必要的复杂性。
为什么要写==
一个非对等关系这么可怕的主意?
因为它破坏了我们的熟悉和直觉,因为从字面上看,相似性,相等性,同余性,同构性,同一性等任何有趣的关系都是等价的。
类型转换
JavaScript不再依赖直观的对等,而是引入了类型转换:
如果操作数不是同一类型,则等于运算符将对其进行转换,然后应用严格比较。
但是如何定义类型转换?通过一系列复杂的规则,有无数例外?
尝试建立等价关系
布尔值。显然true
,false
不相同,应该在不同的类中。
数字。幸运的是,数字的相等性已经很好地定义了,其中两个不同的数字永远不在同一个等效类中。在数学上就是这样。在JavaScript数的概念是稍微变形通过的更奇特的存在-0
,Infinity
和-Infinity
。我们的数学直觉表明,0
并且-0
应该在同一类中(实际上-0 === 0
是true
),而每个无穷大都是一个单独的类。
数字和布尔值。给定数字类,我们应该在哪里放置布尔值?false
变得与相似0
,而true
变得与相似,1
但没有其他数字:
true == 1 // true
true == 2 // false
这里有什么逻辑可以true
结合1
吗?公认1
是杰出的,但也是如此-1
。我个人认为没有任何理由可以转换true
为1
。
而且情况变得更糟:
true + 2 // 3
true - 1 // 0
所以true
确实是1
在所有数字之间转换!这合乎逻辑吗?直观吗?答案留给运动;)
但是呢:
1 && true // true
2 && true // true
唯一的布尔x
与x && true
存在true
的x = true
。证明1
和和2
(以及除以外的任何其他数字0
)都转换为true
!这说明我们的conversion依失败了另一个重要特性- 双射。意味着两个不同的实体可以转换为相同的实体。就其本身而言,这不一定是一个大问题。当我们使用这种转换来描述我们要称呼它的“相同”或“松散相等”的关系时,就会出现一个大问题。但是有一点很明确-它不会是等价关系,也不会通过等价类直观地描述。
但是我们可以做得更好吗?
至少在数学上-绝对是的!布尔和数字之间的一个简单的等价关系,也可以只进行构建false
,并0
在同一类之中。因此,false == 0
将是唯一的非平凡宽松平等。
字符串呢?
我们可以在开头和结尾处修剪空格中的字符串以转换为数字,也可以忽略前面的零:
' 000 ' == 0 // true
' 0010 ' == 10 // true
因此,我们得到了一个简单的字符串规则-修剪前面的空格和零。我们得到一个数字或空字符串,在这种情况下,我们将转换为该数字或零。或者我们没有得到一个数字,在这种情况下,我们不进行转换,因此也没有新的关系。
这样,我们实际上就可以对整个布尔值,数字和字符串获得完美的等价关系!除了……JavaScript设计师显然有另一种意见:
' ' == '' // false
因此,两个都转换为的字符串0
突然变得不相似!为什么或为什么?根据规则,在严格相等的情况下,字符串精确地相等!正如我们所见,这条规则不仅破坏了传递性,而且是多余的!创建另一个运算符==
使其与另一个运算符严格相同的意义===
何在?
结论
如果宽松的等式运算符==
遵守一些基本的数学定律,它可能会非常有用。但是,令人遗憾的是,它的实用性受到了损害。