相等性練習:實作受控制的強制相等搜尋函式
本文是相等性章節的實作練習。前幾篇完整分析了
==演算法、各種角落案例,以及使用準則。這個練習的目標是把這些知識整合起來:在一個受明確規則約束的強制相等比較系統中,實作一個搜尋函式。
練習情境
寫一個 findAll(value, array) 函式,在 array 中找出所有與 value 符合特定強制相等規則的元素,回傳一個包含所有匹配項目的陣列。
這個練習的核心挑戰在於:規則不是直接用 == 就好,而是一套更精確的強制相等規則,涵蓋了我們在這一系列討論中見過的幾乎所有角落案例。
條件說明
findAll(..)函式接受一個值和一個陣列,並回傳一個陣列。允許的強制相等匹配規則如下:
- 完全相同(使用
Object.is(..)) - 字串(空字串或只有空白字元的字串除外)可以匹配數字
- 數字(
NaN及正負無限大除外)可以匹配字串(提示:注意-0的處理!) null可以匹配undefined,反之亦然- boolean 只能匹配 boolean
- 物件只能匹配完全相同的物件參考
- 完全相同(使用
測試範本
javascript
var myObj = { a: 2 };
var values = [null, undefined, -0, 0, 13, 42, NaN, -Infinity, Infinity, "", "0", "42", "42hello", "true", "NaN", true, false, myObj];
console.log(setsMatch(findAll(null, values), [null, undefined]) === true);
console.log(setsMatch(findAll(undefined, values), [null, undefined]) === true);
console.log(setsMatch(findAll(0, values), [0, "0"]) === true);
console.log(setsMatch(findAll(-0, values), [-0]) === true);
console.log(setsMatch(findAll(13, values), [13]) === true);
console.log(setsMatch(findAll(42, values), [42, "42"]) === true);
console.log(setsMatch(findAll(NaN, values), [NaN]) === true);
console.log(setsMatch(findAll(-Infinity, values), [-Infinity]) === true);
console.log(setsMatch(findAll(Infinity, values), [Infinity]) === true);
console.log(setsMatch(findAll("", values), [""]) === true);
console.log(setsMatch(findAll("0", values), [0, "0"]) === true);
console.log(setsMatch(findAll("42", values), [42, "42"]) === true);
console.log(setsMatch(findAll("42hello", values), ["42hello"]) === true);
console.log(setsMatch(findAll("true", values), ["true"]) === true);
console.log(setsMatch(findAll(true, values), [true]) === true);
console.log(setsMatch(findAll(false, values), [false]) === true);
console.log(setsMatch(findAll(myObj, values), [myObj]) === true);
console.log(setsMatch(findAll(null, values), [null, 0]) === false);
console.log(setsMatch(findAll(undefined, values), [NaN, 0]) === false);
console.log(setsMatch(findAll(0, values), [0, -0]) === false);
console.log(setsMatch(findAll(42, values), [42, "42hello"]) === false);
console.log(setsMatch(findAll(25, values), [25]) === false);
console.log(setsMatch(findAll(Infinity, values), [Infinity, -Infinity]) === false);
console.log(setsMatch(findAll("", values), ["", 0]) === false);
console.log(setsMatch(findAll("false", values), [false]) === false);
console.log(setsMatch(findAll(true, values), [true, "true"]) === false);
console.log(setsMatch(findAll(true, values), [true, 1]) === false);
console.log(setsMatch(findAll(false, values), [false, 0]) === false);
// ***************************
function setsMatch(arr1, arr2) {
if (Array.isArray(arr1) && Array.isArray(arr2) && arr1.length == arr2.length) {
for (let v of arr1) {
if (!arr2.includes(v)) return false;
}
return true;
}
return false;
}詳細解法將在下一篇說明。
此文章是 FrontendMasters 上的 Deep JavaScript Foundations, v3 課程筆記
