在此整理并持续更新一些常见的手写题,对于深入理解 JS 底层原理,或者突击面试,都有一定帮助 :
手写 instanceof
function isInstanceof(obj, fn) {
if (!(typeof obj === 'object' && obj !== null)) return false // 非对象类型一律为 false
let proto = obj // 获取对象的原型
while ((proto = Object.getPrototypeOf(proto))) {
if (proto === fn.prototype) return true
}
return false
}
手写 Object.create
function objectCreate(obj) {
function F() {}
F.prototype = obj
return new F()
}
手写 new
function New(ctor, ...args) {
if (typeof ctor !== 'function') throw `${ctor} is not a constructor`
const obj = Object.create(ctor.prototype)
const res = ctor.apply(obj, args) // 考虑构造函数有返回值的情况,直接执行
const isObject = typeof res === 'object' && res !== null
const isFunction = typeof res === 'function'
return isObject || isFunction ? res : obj
}
手写 debounce 防抖
// 普通防抖
function debounce(fn, wait = 1000) {
let timer
return function (...args) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
timer = null
fn(...args)
}, wait)
}
}
// 可控制是否立即执行的防抖(比较实用)
function debounceImmediate(fn, wait = 2000, immediate = true) {
let timer
return function (...args) {
var runNow = !timer && immediate
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
timer = null
if (!immediate) fn(...args)
}, wait)
if (runNow) fn(...args)
}
}
手写 throttle 节流
function throttle(fn, wait = 1000) {
let previous = 0
let timer
return function (...args) {
let now = Date.now()
let remain = wait - (now - previous)
if (remain <= 0) {
fn(...args)
previous = now
} else if (!timer) {
timer = setTimeout(() => {
fn(...args)
previous = Date.now()
timer = null
}, remain)
}
}
}
手写 compose 函数
async function compose(middlewares, ctx) {
let currentIndex = 0
let currentFunc = middlewares[currentIndex]
const next = async () => {
currentIndex++
if (currentIndex >= middlewares.length) return
currentFunc = middlewares[currentIndex]
return currentFunc(ctx, next)
}
return currentFunc(ctx, next)
}
手写 cluster-worker 模型
const cluster = require('cluster')
const http = require('http')
// 如果是主进程
if (cluster.isMaster) {
console.log('is master')
// fork 出 worker 子进程
const worker = cluster.fork()
;['error', 'exit', 'listening', 'message', 'online'].forEach(event => {
worker.on(event, msg => {
console.log(`[${event}] from worker:`, msg)
})
})
} else {
console.log('is worker')
http
.createServer((req, res) => {
process.send(`${req.url}`)
res.end(`Hello World: ${req.url}`)
})
.listen(8000)
}
手写 flat 函数
function flat(arr, depth = 1) {
if (depth <= 0) return arr
const ret = []
for (let i = 0; i < arr.length; i++) {
const it = arr[i]
if (Array.isArray(it)) {
ret.push(...flat(it, depth - 1))
} else {
ret.push(it)
}
}
return ret
}
TODO:持续更新...