這幾天看到一個大三大佬面試位元組跳動的蚊子,突然覺得自己太辣雞了···校招的題我一半多都不會啊···趕緊潛下心來學習學習提(an)高(wei)自己,邊翻掘金邊谷歌,簡單實現了幾個常用函式···(借鑑了太多人的文章了··弄不清了··沒法寫出引用了··大佬們請諒解··)
深拷貝 deepClone
function deepClone(target, hash = new WeakMap()) {
// 不是物件或者是null 直接返回
if (typeof target !== "object" || target == null) return target;
// 通過WeakMap判斷是否已有 有則返回物件引用
if (hash.has(target)) return hash.get(target);
// 判斷是陣列還是字串
const result = target instanceof Array ? [] : {};
// 結果放進WeakMap裡,key是target,值是result
hash.set(target, result);
// for in遍歷
for (const key in target) {
// 避開原型鏈上的屬性
if (Object.prototype.hasOwnProperty.apply(target,key)) {
// 遞迴呼叫
result[key] = _deepClone(target[key]);
}
}
// 返回結果
return result;
}
複製程式碼
防抖 debounce
function debounce(handler, wait = 300, immediate = false) {
// 宣告一個變數timer
let timer;
// 判斷引數是否符合預期
if (typeof handler !== "function") throw new TypeError("The first params shoule be a Function");
if (typeof wait !== "number") throw new TypeError("The second params shoule be a Number");
return function() {
// 快取上下文和引數
const context = this,
args = [...arguments];
// 如果timer存在就清除timer
timer && clearTimeout(timer);
if (immediate) {
// immediate為true且定時器不存在,則設定定時器,並在指定時間後timer設定為null
const callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait);
// 且立即執行一次handler,通過apply繫結上下文和傳入引數
callNow && handler.apply(context, args);
} else {
// immediate為false則設定定時器
timer = setTimeout(() => {
handler.apply(context, args);
}, wait);
}
};
}
複製程式碼
節流 throttle
function throttle(handler, wait = 300) {
// 宣告一個變數timer
let timer;
return function() {
// timer存在則直接返回怎麼也不幹
if (timer) return;
// 快取上下文和引數
const context = this,
args = [...arguments];
// 設定定時器
timer = setTimeout(() => {
// 執行handler,通過apply繫結上下文和傳入引數
handler.apply(context, args);
// timer設定為null
timer = null;
}, wait);
};
}
複製程式碼
是否是純物件 isPlainObject
function isPlainObject(obj) {
return Object.prototype.toString.call(obj) === "[object Object]";
}
複製程式碼
深度對比 isEqual
function isEqual(target1, target2) {
// 直接先對比,相等就返回
if (target1 === target2) return true;
const isPlainObject = obj => Object.prototype.toString.call(obj) === "[object Object]";
// 如果兩者任意一個不是純物件,直接返回對比結果
if (!isPlainObject(target1) || !isPlainObject(target2)) return target1 === target2;
// 拿到兩個keys的陣列,長度不一致那肯定不一樣
const target1Keys = Object.keys(target1);
const target2Keys = Object.keys(target2);
if (target1Keys.length !== target2Keys.length) return false;
// 以target1為基準遍歷,遞迴呼叫isEqual對比每一項,任何一項不一樣直接返回false
for (const key in target1) {
if (target1.hasOwnProperty(key)) {
if (!isEqual(target1[key], target2[key])) return false;
}
}
// 全一樣
return true;
}
複製程式碼
拍平陣列 flatArray
function flatArray(arr, depth = Infinity) {
// 不是陣列則報錯
if (!arr instanceof Array) throw new TypeError("Expect Array");
// 判斷是否支援ES10的flat方法
if (Array.prototype.flat) {
// 支援則直接呼叫
return arr.flat(depth);
} else {
// 看陣列內元素是否都是普通型別
const isDeep = arr.some(item => Array.isArray(item));
// 如果都是普通型別則直接返回
if (!isDeep) return arr;
// 用陣列concat方法拍平陣列第一層
const result = [].concat(...arr);
// 遞迴呼叫,拍平深層陣列
return flatArray(result);
}
}
複製程式碼
陣列快排 quickSort
function quickSort(target) {
// 不是陣列或者陣列長度小於2,則直接返回
if (Object.prototype.toString.apply(target) !== '[object Array]' || target.length < 2) return target
// 拷貝一份陣列
const _arr = [...target]
// 找到並取出基準元素
const pivotItem = _arr.splice(Math.floor(_arr.length / 2), 1)
// 定義兩個臨時陣列,分別儲存比基準小和比基準大的元素
const smallerArr = []
const biggerArr = []
// 遍歷陣列,將元素分類
for (let index = 0; index < _arr.length; index++) {
const element = _arr[index]
pivotItem > element ? smallerArr.push(element) : biggerArr.push(element)
}
// 將兩個臨時陣列遞迴呼叫,並將兩個陣列和基準元素合併起來
const result = this._quickSort(smallerArr).concat(pivotItem, this._quickSort(biggerArr))
// 返回新陣列
return result
},
複製程式碼
陣列氣泡排序 bubbleSort
function bubbleSort(target) {
// 不是陣列或者陣列長度小於2,則直接返回
if (Object.prototype.toString.apply(target) !== '[object Array]' || target.length < 2) return target
// 拷貝一份陣列
const _arr = [...target]
// 遍歷陣列
for (let index = 0; index < _arr.length; index++) {
for (let innerIdx = index + 1; innerIdx < _arr.length; innerIdx++) {
// 相鄰元素兩兩對比,元素交換,大的元素交換到後面
if (_arr[index] > _arr[innerIdx]) {
[_arr[index], _arr[innerIdx]] = [_arr[innerIdx], _arr[index]]
}
}
}
// 返回新陣列
return _arr
}
複製程式碼