判斷兩個物件的內容是否相等
阿新 • • 發佈:2020-05-03
由於在做[鍵盤導航元件](https://github.com/happyCoding1024/keyboardnavigation)的專案時,有這樣一個需求,當用戶傳入按鍵字母和網址的對映時,如果和 localStorage 中的不一樣那麼就用 localStorage 中儲存的,這個時候就需要比較兩個物件的內容是否相等,但是在 JS 中物件是一種引用型別.
```js
obj1 = {
a: 1
}
obj2 = {
a: 1
}
console.log(obj1 === obj2) // false
```
即使兩個物件的內容完全相同,因為它們的地址不同,因此 `obj1 === obj2` 會返回 fasle。
所以自己根據深拷貝時遞迴的思想寫了一個比較兩個物件之間內容是否相同的函式。
```js
function compareObject (obj1, obj2) {
// 遞迴終止條件,當 obj1 或 obj2 不是物件時,此時就可以進行判斷了
if (typeof obj1 !== 'object' || typeof obj2 !== 'object') {
if (obj1 === obj2) {
return true
} else if (obj1 !== obj2) {
return false
}
}
// 獲取物件的自由屬性組成的陣列
const obj1PropsArr = Object.getOwnPropertyNames(obj1)
const obj2PropsArr = Object.getOwnPropertyNames(obj2)
// 如果陣列的長度不相等,那麼說明物件屬性的個數都不同,返回 false
if (obj1PropsArr.length !== obj2PropsArr.length) {
return false
}
// 記錄當前 compareObject 的返回值,預設是 true
let status = true
for (key of obj1PropsArr) {
status = compareObject(obj1[key], obj2[key])
// 關鍵程式碼,當 status 為 false 時下面就不用再進行判斷了,說明兩個物件的內容並不相同
// 如果沒有下面這條語句,那麼只要物件底層的內容是相同的那麼就返回 true
if (!status) {
break
}
}
// 每次 compareObject 執行的返回結果
return status
}
```
測試程式碼:
```js
// 判斷兩個物件的內容相等
const obj1 = {
a: 1,
b: {
c: 2,
d: {
e: 4
}
}
}
const obj2 = {
a: 1,
b: {
c: 2,
d: {
e: 4
}
}
}
console.log(compareObject(obj1, obj2)) // true
// 判斷兩個物件的內容不相等
const obj1 = {
a: 1,
b: {
c: 2,
d: {
e: 4
}
}
}
const obj2 = {
a: 1,
b: {
c: 2,
d: {
e: 5
}
}
}
console.log(compareObject(obj1, obj2)) // false
```
接下來再來強調一下 `compareObject` 函式中第 23 行這句關鍵程式碼,如果沒有這條語句那麼最後的返回結果只會取決於兩個物件最底層屬性(最後一次)的比較結果。
```js
if (!status) {
break
}
```
例如,我將兩個物件變為下面這樣:
```js
const obj1 = {
a: 1,
b: {
c: 3, // 和 obj2 不相等
d: {
e: 4
}
}
}
const obj2 = {
a: 1,
b: {
c: 2,
d: {
e: 4
}
}
}
console.log(compareObject(obj1, obj2)) // true
```
可以看到最後的返回結果是 true,因為最後的一次比較是 e 屬性,它們的值是相等的。
上面這樣的寫法應該還有一些情況沒有考慮到,對於我的專案需求而言已經足夠了,如果哪位小夥伴發現了希望可以提出來,然後再將它改進一下,非常