This post was writteen in Chinese,Original Post.
Since this post had not been translate to English,Please use the tool provided to translate.
Javascript
在javaScript里,怎么比较两个变量是否相等。
a == b |
那么,下面的代码会输出什么呢?
1 | apple = [1, 2]; |
竟然是false!你说,这怎么可能?他们俩明明是一样的呀。
实际上js的文档有介绍==的用途, js会首先检查左右两边的变量是不是相同的类型,如果类型相同才进一步继续比较。如果这两个变量的类型都是object,那么js会查看这两个变量是否指向同一个对象。
我们回头看apple = [1,2], 正如它所表达出来的一样 “定义一个数组,它的名字叫apple”。这个数组可能被系统分配到内存的任何位置,apple就是一张写着数组所在内存位置的名片,仅此而已。所以,当我们定义apple = [1, 2]; banana = [1, 2];的时候,一个数组会被储存到内存某个位置,可以通过apple找到它;另一个数组也会被存到内存的某个位置,可以通过banana来找到它。这两个数组虽然元素都一样,但却是储存在内存不同位置的两个数组。在进行严格比较的时候,它们俩不是同一个对象,所以是false。
我们再来看看另一个比较
1 | apple = {"name":"Alice"}; |
猜一下发生了什么,为什么是false?
我们定义了一个哈希,并且有一个叫apple的变量指向了它。我们又定义了一个变量banana,它指向了apple指向的哈希;现在,我们定义一个新的,和之前一摸一样的哈希,并且让apple指向它。如此,apple和banana指向的数据便是不同位置的两个相同内容的哈希,他们虽然长得一样,但不是同一个对象。
Two distinct objects are never equal for either strict or abstract comparisons.
我们看看python和ruby语言有没有这个问题
Ruby
Ruby里面有几种比较方法,一个方法是equal?()。这个方法是BasicObject(所有其它类的父类)所定义的。
1 | a = [1, 2, 3] |
当我们用==比较两个数组的时候,ruby会逐个比较数组中的元素,只有每个元素都相等,并且在数组中的位置也一样的时候,两个数组才相等。但当我们用equal?函数比较两个数组,除非它们所指的,是同一个元素,否则就是false。
此外,Ruby还提供了eql?方法来进行比==更为严格的比较。它会将两个对象的哈希值进行比较,只有当哈希值相等的时候,它们才相等。大多数ruby的可比较对象都有一个.hash方法, 该方法返回的哈希值被eql?用于比较两个对象是否相等。
Python
Python里面用is来确定两个变量是否指向同一个对象,比如说
1 | a = [1, 2, 3] |
和js中的===一样,如果比较的两个对象所指的不是同一个对象,is的返回值就是false。
总结
Js的==有一个特性,它不会给我们直接比较两个对象(object),而是先变换类型,然后再严格比较。所谓严格比较,指的是当两个比较对象是同一个对象。所谓对象,指的是js中的Object类型。