JS 中的常见手写题

320 阅读1分钟

在此整理并持续更新一些常见的手写题,对于深入理解 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:持续更新...