前端手写面试题大集合

160 阅读2分钟

1. 手写new

function _new(constructor: Function, ...args: any[]) {
  //1. 判断constructor 是否是一个对象
  if( typeof constructor !== 'function') throw 'constructor must be a function';

  //2. 创建一个"纯粹对象"并继承构造函数的原型链
  const obj = Object.create(constructor.prototype);

  //3. 初始化constructor 并把其实例中的属性和执行结果添加到新对象中(将obj的this指向constructor)
  const result = constructor.apply(obj, args);

  //4. 如果constructor的返回值(result)是对象则返回result,否则返回实例obj
  return result instanceof Object ? result : obj
}

2. 手写instanceof

const _instanceof = (instance: any, constructor: any):boolean => {
  //1.过滤非对象
  if( !instance || !['object', 'function'].includes(typeof instance) ) return false
  
  //3. 获取实例的原型
  let instancePrototype = Object.getPrototypeOf(instance) // == instancePrototype.__proto__

  //判断实例的原型链中是否有原型和constructor的原型相等
  while (instancePrototype) {
    if( instancePrototype === constructor.prototype) return true
    instancePrototype =  Object.getPrototypeOf(instancePrototype)
  }
  
  //4. 未找到返回false
  return false
  
}

3. 判断字符是否为完整的括号

const map: {[K in string]: string} = {
  ')': '(',
  '}': '{',
  ']': '[',
}

const hasBrackets = (str: string) => {
  const len = str.length 
  if( len % 2 !== 0) return false
  for(let i=0; i < len / 2; i++ ) {
    if( str[i] !== map[str[len - i - 1]]) return false
    return true
  }
}

['()', '[]', '{}', '({})', '[()', '[(])'].forEach(e => {
  console.log( hasBrackets(e) );
})

// 答案:true true true true false false

4. 微型数据结构


interface NodeProps {
  value: any
  next?: NodeProps
}

class Node {
  next: NodeProps['next'];
  value: NodeProps['value'];
  constructor(value: any) {
    this.value = value
  }
}

export default class Queue {
  private head?: NodeProps;
  private tail?: NodeProps;
  private len: number = 0;
  constructor() {
    this.clear()
  }

  clear() {
    this.head = undefined
    this.tail = undefined
    this.len = 0
  }

  enqueue(value: any) {
    const node = new Node(value)
    if( this.head && this.tail ) {
      this.tail.next = node
      this.tail = node
    } else {
      this.head = node
      this.tail = node
    }
    this.len++
  }

  dequeue() {
    const current = this.head
    if( !current ) return undefined
    this.head = current.next
    this.len--
    return current.value
  }

  get size() {
    return this.len
  }

  *[Symbol.iterator]() {
    let current = this.head
    while(current) {
      yield current.value
      current = current.next
    }
  }

}

5. 手写防抖debounce

const debounce = (fn: Function,wait: number = 500) => {
  let timer: NodeJS.Timeout
  
  return (...args: any[]) => {

    timer && clearTimeout( timer )

    timer = setTimeout(() => {
      fn.apply(fn, args)
    }, wait);

  }
}

6. 手写节流throttle

const throttle = (fn: Function, wait: number = 500) => {
  let pre = new Date().valueOf()

  return (...args: any[]) => {
    const now = new Date().valueOf()

    if( now - pre >= wait ) {
      fn.apply(fn, args)
      pre = now
    }

  }
}

7.节流

const throttle = (fn: Function, wait: number = 500) => {
  let pre = new Date().valueOf()

  return (...args: any[]) => {
    const now = new Date().valueOf()

    if( now - pre >= wait ) {
      fn.apply(fn, args)
      pre = now
    }

  }
}

8. 防抖

const useDebounceWithUseRef = (fn: Function, wait: number = 500) => {
  let timer = React.useRef<ReturnType<typeof setTimeout>>()
  
  return React.useCallback((...args: any[]) => {
    timer.current && clearTimeout(timer.current)

    timer.current = setTimeout(() => {
      fn.apply(fn, args)
    }, wait);
  }, [wait])

}

9. 柯里化

const currieization = (...args: number[]) => {
  function inner(...args2: any[]) {
    args.push( ...args2 )
    return inner
  }

  inner.toString = () => args.reduce((total, num) => total + num)

  return inner
}

10. 随机颜色

const getRandomColor:() => string = () => {
  return `#${parseInt( `${Math.random() * 0xffffff}` ).toString(16)}`
}

11. 手写一个bind

Function.prototype._bind = function(instance = window) {
  if( instance === null || instance === undefined ) return undefined
  if( typeof instance !== 'object' ) instance = Object.create(Object.getPrototypeOf(instance))

  const fn = Symbol()
  instance[fn] = this

  return (...args) => {
    const res = instance[fn](...args)
    delete instance[fn]
    return res
  }
}

12. 手写一个call

Function.prototype._call = function(instance = window, ...args){
  if( instance === null || instance === undefined ) return undefined
  if( typeof instance !== 'object' ) instance = Object.getPrototypeOf(instance)

  const fn = Symbol('fn')
  instance[fn] = this
  const res = instance[fn](...args)
  delete instance[fn]

  return res
}

13. 手写一个apply

Function.prototype._apply = function(instance = window, args = [] ) {
  if( instance === null || instance === undefined ) return undefined
  if( typeof instance !== 'object' ) instance = instance.__proto__

  instance[Symbol.for('fn')] = this
  const res = instance[Symbol.for('fn')](...args)
  delete instance[Symbol.for('fn')]

  return res 
}