問題描述:
在JavaScript中,數值的比較是比較簡單的,使用相等(==)和全等(===)符號基本上可以解決大多數非對象的比較;但是相等(==)和全等(===)符號在對象 object 的比較上,就不能滿足所有的要求了,如下面的代碼:
1 let obj_a = { 2 name: "jack", 3 old: 12 4 } 5 6 let obj_b = { 7 name: "lucy", 8 old: 13 9 } 10 11 let obj_c = { 12 name: "lucy", 13 old: 13 14 } 15 16 let obj_d = obj_b 17 18 console.log(obj_a === obj_b) // false 19 console.log(obj_b === obj_c) // false 20 console.log(obj_b === obj_d) // true
上面代碼中 obj_b 和 obj_c 是不等的,但是和 obj_d 是相等的,這是因為全等符號 === 在比較對象的時候,比較的是對象的地址,換句話來說:全等符號判斷的是兩個對象是否是一個對象,而不能判斷兩個對象是否數值相等,事實上,在大多數情況下,使用全等符號去判斷兩個對象返回的均是 false
解決方法:
那如果需要判斷兩個對象在字面意義上是否相等,該才去什么樣的操作?答案是遍歷兩個對象,然后在一一比較 key-value 對;如果對象發生了嵌套, 那么使用遞歸即可; 為了方便使用,可以將比較的方法抽象成為下面的函數:
const isObjectValueEqual = (a, b) => { // Object.getOwnPropertyNames()方法返回一個由指定對象的所有自身屬性的屬性名(包括不可枚舉屬性但不包括Symbol值作為名稱的屬性)組成的數組 // 換句話來說 Object.getOwnPropertyNames()方法返回的是對象所有 key 組成的數組 list let aProps = Object.getOwnPropertyNames(a) let bProps = Object.getOwnPropertyNames(b) if (aProps.length != bProps.length) { return false } for (let i = 0; i < aProps.length; i++) { let propName = aProps[i] if (typeof a[propName] === 'object') { let judge = isObjectValueEqual(a[propName], b[propName]) if (!judge) { return false } } else if (a[propName] !== b[propName]) { return false } } return true }
結論:
1)===主要用於判斷對象是否是同一個對象,而不能用來判斷兩個存儲地址不一致的對象在屬性上是否完全相等
2)判斷存儲地址不一致的對象在屬性上是否完全相等可以使用如上函數
3)普通變量可以使用 set 集合的方法方便地去重,但是對象變量是不能的(這點可以自己驗證)