文章

前端面試手寫練習 - isEqual

文章發表於

問題

當我們想要按值而不是按引用比較複雜的數據類型時,isEqual 非常有用。這篇文章將討論如何實作一個 isEqual 函式,我們需要能夠支援以下數據類型:

  1. 原始類型 (primitives)
  2. 物件 (plain objects, object literals)
  3. 陣列 (arrays)
function isEqual(a: any, b: any): boolean

範例

isEqual 非常直觀,它將兩個值進行比較,如果它們是相等的,則返回 true,否則返回 false

const obj1 = { a: 1, b: 2 }
const obj2 = { a: 1, b: 2 }
console.log(isEqual(obj1, obj2)) // true
const arr1 = [1, obj1, 3]
const arr2 = [1, obj2, 3]
console.log(isEqual(arr1, arr2)) // true

練習區

在了解問題後,可以嘗試先寫下您的思路,再到下方的練習區域實際寫出程式碼。

import { add } from './add';

describe('add', () => {
  test('Commutative Law of Addition', () => {
    expect(add(1, 2)).toBe(add(2, 1));
  });
});

Open browser consoleTests

追問

  1. 如何處理陣列或是物件中的循環引用 (circular references)? (Hint: 使用 WeakMap)

筆者思路

  1. 定義 base case

    • 如果 a === b 直接回傳 true
  2. 如果 a 與 b 都是陣列

    • 如果 b 長度與 a 不同,直接回傳 false
    • 使用 every 來檢查每個元素是否相等
  3. 如果 a 與 b 都是物件

    • 取得 a 與 b 的 key
    • 如果 key 長度不同,直接回傳 false
    • 使用 every 來檢查每個 key 是否相等

筆者解答

function isEqual(a, b) {
if (a === b) {
return true;
}
if (Array.isArray(a)) {
if (a.length !== b.length) {
return false;
}
return a.every((item, idx) => isEqual(item, b[idx]));
}
if (typeof a === 'object' && typeof b === 'object') {
let aKeys = Object.keys(a);
let bKeys = Object.keys(b);
if (aKeys.length !== bKeys.length) {
return false;
}
return aKeys.every((k) => isEqual(a[k], b[k]));
}
return false;
}

相關題目

  1. bigfrontend.dev - isEqual
如果您喜歡這篇文章,請點擊下方按鈕分享給更多人,這將是對筆者創作的最大支持和鼓勵。