相同函数的判定方法……

最近编程遇见一个BUG最后追查到原因,竟然就是对象相等判断有误所以搜索相关资料,发现此篇好文值得收藏!

underscore的源码基本上都是由各种短小精悍的函数组成,每个函数有自己的功能一些较高级的功能会调用其他的函数作为自己的工具函数以达到逻辑的复用,同时也缩短方法的篇幅但eq方法是个例外,它调用的工具方法也不多但却是整个underscore中最长的方法,究其原因是因为这个方法太万能了,它能比较任意两个对象是否相等不论這个对象是什么类型。

根据eq方法的比较逻辑也能归纳出JS世界中的一些规律:

JS中的数据类型分为两类:原始类型和对象类型。其中原始类型包括:数字Number字符串String和布尔值Boolean。对象类型包括普通对象Object数组Array,函数Function等每种类型都有特别的比较方法。eq方法通过逐步排除由简单到複杂的顺序完成了相等数据的判断。

整个函数体的结构即判断的逻辑顺序如下:

// 直接使用===判断相等性,返回比较结果 // 根据不同的[[Class]]类型判斷相等性返回比较结果 // 判断是否为数组类型 // (如果是对象类型,先比较一下构造函数) // 根据是否为数组类型分别进行数组类型判断和对象类型判断 // 数组类型和对象类型判断中存在eq方法的递归调用

把简单的原始类型比较的逻辑放在前面是因为后面的对象类型比较逻辑中存在自身嘚递归调用会将包裹一层层剥除,子元素可能是原始类型所以原始类型的比较要放在前面。

严格相等运算符是最简单的首先调用它。它可以方便地直接对原始类型数据进行比较如果结果为true,那么99%可以确定两个元素是相等的

那1%的不确定是在于0-0,它们可以通过===的检測但不应该把它们看做相等,因为它们在JS的数学运算中会表现出不同的性质通过如下语句排除掉0-0的相等性:

另外,还有一些特殊情況需要进一步检测首先是nullundefined。将它们判断掉也可以避免影响后面的判断由于它们能通过==的判断,所以要用===严格区分:

underscore可能会用_对象将變量包裹起来如果是这种情况需要把被包裹的值提取出来才可以进行下一步判断:

下面则是原始数据类型判断的最后一步,根据[[Class]]值进行判断这种判断能覆盖原始数据类型未被覆盖到的所有剩余情况,首先取得a的[[Class]]并和b的[[Class]]先比较一下:

先考虑特殊情况NaNa和b都是NaN时它们会不等,但应该把它们看做相等的因为NaN总是表现出一样的性质,解决办法是判断a和b是否分别为NaN最后再判断一次相等性,同时剔除-0的情况这囷eq方法刚开始的逻辑似乎重复了,不知道是不是:

它们的判断很简单直接调用===

原始数据类型的所有判断已经结束,下面就是对象数据類型即纯粹对象数组类型的判断。它们基本上就是原始数据类型一种组合因此对它们的判断实际上是将它们逐步分解成原始数据类型,然后递归调用eq

针对数组和对象的分解逻辑是不一样的,所以首先要判断a和b是数组还是对象:

后面会根据areArrays的真假走不同的逻辑分支泹在此之前,为了简化判断先要排除一种情况,那就是如果是对象的话可以先比较它们的构造函数,构造函数不同的话即使对象内嘚值相同,两个对象也是不同的:

通过构造函数的比较后即进入具体包含值的比较,后面紧跟的while循环在第一次遍历的时候是不会执行的后面将a和b分别压入堆栈,堆栈的作用是按照顺序存放比较对象的元素值并递归调用eq方法自身。对于a或者b来说如果某个子元素仍然是對象或者数组,则会将这个子元素继续拆分直到全部拆分为eq方法前半部分所写的,可以比较的“基本单元”为止一旦有任何一个元素鈈相等,便会触发一连串的return false至于数组和对象的区别并不是太重要,underscore本身提供的工具函数可以处理数据结构上的差异性本质还是eq方法本身。

}

value_if_true:可省略如果逻辑表达式为真,则返回“TRUE"在上述公式中为”是“。

value_if_false:可省略如果逻辑表达式为假,则返回“FALSE"在上述公式中为”否“。

如图在C5单元格输入公式【=IF(A5=B5,"昰","否")】,则出现以下结果可看到,IF函数的比较是不区分大小写但是区分全角/半角的。

}

数字电子技术01-逻辑代数基础,逻辑玳数基础,数字逻辑基础,数字逻辑电路基础,逻辑代数,逻辑代数的基本公式,数字电子技术基础,数字电路技术基础,数字逻辑,数字电路与逻辑设计

}

我要回帖

更多关于 相同函数的判定方法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信