1.多種方式實現(xiàn)數(shù)組去重、扁平化、對比優(yōu)缺點
數(shù)組去重
// 普通數(shù)組去重
function dedupe(arr) {
let rets = []
for (let i = 0; i < arr.length; i++) {
if (!rets.includes(arr[i])) rets.push(arr[i])
}
return rets
}
function dedupe(arr) {
let rets = []
arr &&
arr.forEach(function(item) {
if (!rets.includes(item)) rets.push(item)
})
return rets
}
function dedupe(array) {
return [...new Set(array)]
}
// 對象數(shù)組去重 key為獨立唯一標(biāo)識
function unique(arr, key) {
const hash = {}
const res = []
for (let i = 0; i < arr.length; i++) {
if (!hash[arr[i][key]]) {
res.push(arr[i])
hash[arr[i][key]] = true
}
}
return res
}
const unique = (arr, key) => {
let hash = {}
return arr.reduce((accumulator, currentValue) => {
hash[currentValue[key]]
? ''
: (hash[currentValue[key]] = true && accumulator.push(currentValue))
return accumulator
}, [])
}
扁平化
function flatten(arr) {
let rets = []
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
rets = rets.concat(flatten(arr[i]))
} else {
rets.push(arr[i])
}
}
return rets
}
function flatten(arr) {
let rets = []
arr &&
arr.forEach(item => {
if (Array.isArray(item)) {
rets = rets.concat(flatten(item))
} else {
rets.push(item)
}
})
return rets
}
const flatten = arr =>
arr.reduce(
(accumulator, currentValue) =>
accumulator.concat(
Array.isArray(currentValue) ? flatten(currentValue) : currentValue
),
[]
)
2.多種方式實現(xiàn)深拷貝、對比優(yōu)缺點
// 乞丐版
function deepCopy(obj) {
return JSON.parse(JSON.stringgify(obj))
}
// 面試夠用版
function deepCopy(obj) {
let result = obj.constructor === Array ? [] : {}
for (let i in obj) {
result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i]
}
return result
}
3.手寫函數(shù)柯里化工具函數(shù)、并理解其應(yīng)用場景和優(yōu)勢
理解柯里化:用閉包把參數(shù)保存起來,當(dāng)參數(shù)的數(shù)量足夠執(zhí)行函數(shù)了,就開始執(zhí)行函數(shù)。
// ES6騷寫法
const curry = (fn, arr = []) => (...args) =>
(arg => (args.length === fn.length ? fn(...args) : curry(fn, arg)))([
...arr,
...args
])
4.手寫防抖和節(jié)流工具函數(shù)、并理解其內(nèi)部原理和應(yīng)用場景
/**
* description: 防抖
* param {Function} fn - 定時器每次執(zhí)行調(diào)用的函數(shù)
* param {Number} [delay = 300] - 定時器執(zhí)行時間間隔
* author: yanxu gong
* update: 2019-11-13 9:50
*/
function debounce(fn, delay = 300) {
let timer = null
return (...args) => {
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
/**
* description: 節(jié)流
* param {Function} fn - 定時器每次執(zhí)行調(diào)用的函數(shù)
* param {Number} [delay = 500] - 定時器執(zhí)行時間間隔
* author: yanxu gong
* update: 2019-11-13 9:50
*/
function throttle(fn, delay = 500) {
let flag = true
return (...args) => {
if (!flag) return
flag = false
setTimeout(() => {
fn.apply(this, args)
flag = true
}, delay)
}
}
5.實現(xiàn)一個 sleep 函數(shù)
Promise 版本
function sleep(time) {
return new Promise(resolve => setTimeout(resolve, time))
}
const t1 = +new Date()
sleep(3000).then(() => {
const t2 = +new Date()
console.log('t2 - t1:' + (t2 - t1))
})
優(yōu)點:這種方式實際上是用了 setTimeout,沒有形成進(jìn)程阻塞,不會造成性能和負(fù)載問題。
缺點:雖然不像 callback 套那么多層,但仍不怎么美觀,而且當(dāng)我們需要在某過程中需要停止執(zhí)行(或者在中途返回了錯誤的值),還必須得層層判斷后跳出,非常麻煩,而且這種異步并不是那么徹底,還是看起來別扭
Async/Await 版本
function sleep(time) {
return new Promise(resolve => setTimeout(resolve, time))
}
;(async function() {
console.log('Do some thing, ' + new Date())
await sleep(3000)
console.log('Do other things, ' + new Date())
})()
缺點: ES7 語法存在兼容性問題,有 babel 一切兼容性都不是問題