Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

JavaScript中的各种相等比较

  对于JavaScript的初学者来说“==”这个运算符是个非常可怕的东西,要稍微花点时间才能搞明白。实际上JavaScript对值的相等判断有很多不同的算法,“==”只是最常用的一种。由于NaN和正负零的涉入,除了“==”和“===”之外还有SameValue和SameValueZero算法。
  很早以前的文章中就已经对JavaScript的“==”运算符做过详细介绍,这里就不复述了。至于“===”实际上只是在“==”运算符上多加个类型比较而已。
  先来说一下NaN这东西。为什么NaN不会等于它自身呢?我以前好像也有说过这个问题,NaN并不是一个数,而是一类数。就比如说人类,随便两个人,他们都是人类,如果以“同类”这个概念来判断相等的话,任何两个人都是相等的。逻辑上完全没问题,但是这种相等在日常生活中并不实用,我们更倾向于判断个体的相等,任何两个人都是不同的人,所以他们是不等的。“==”和“===”运算符比较的就是个体,而NaN是群集概念,以衡量个体的标准去衡量一个群集概念,当然就造成了永远都不等的情况。以上这些是从逻辑上分析的,而且大前提是NaN是一个群集的概念。那么为什么NaN是一个群集的概念?怎么证明?其实只要看IEEE764的定义就能知道,NaN这个值对应的并不是一个具体的字节值,而是很多字节值都被当做NaN来解析,所以说NaN是一个群集概念。
<script>
//定义a和b两个强类型浮点数组
var a=new Float32Array(new Uint32Array([2143289344]).buffer);
var b=new Float32Array(new Uint32Array([2143289345]).buffer);
//它们都是NaN
console.log(a); //[NaN]
console.log(b); //[NaN]
//但实际上他们在内存中的字节值是不同的
console.log(new Uint32Array(a.buffer)); //2143289344
console.log(new Uint32Array(b.buffer)); //2143289345
</script>
  接着再来说一说正负零。也许初等数学中对正负零确实没什么概念,但高数中经常会出现函数在某点上不连续,左右极限相等的情况。比如最典型的反比例函数 <script>
//反比例函数
function f(x){return 1/x;};
//在0点的左右极限不等
console.log(f(0)==f(-0)); //false
</script>
  或者一些三角函数,比如tan函数在π/2上不连续等(不过π/2这里有个无理数,会因为浮点数精度的影响看不出差异)。所以在某些情况下,区分正负零还是很有意义的。以上是数学上的分析,实际上正负零在内存中的字节值也是不等的,这在IEEE754中也有定义。
<script>
var a=new Float32Array([0]);
var b=new Float32Array([-0]);
console.log(new Uint8Array(a.buffer)); //[0, 0, 0, 0]
console.log(new Uint8Array(b.buffer)); //[0, 0, 0, 128]
</script>
  ES5中定义了SameValue算法,它对应的接口是Object.is,可以将两个NaN视为相同,将正负零视为不同,在这两种情况下是和“==”完全相反的结果。 <script>
Object.is(NaN,NaN); //true
Object.is(0,-0); //false
</script>
  ES6中又定义了SameValueZero算法,它对两个NaN和正负零都视为相同,这个算法没有直接的接口,不过Set之类的对象就是使用这个算法。 <script>
var s=new Set;
s.add(0);
s.add(NaN);
console.log(s.has(-0)); //true
console.log(s.has(NaN)); //true
</script>
  看到这么复杂的相等对比,是不是感觉不会再爱了?相比之下还是最初的“==”运算符比较有爱吧。。
网名:
54.198.108.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^