핸드 코드

4067 단어
Function.prototype.mycall = function(context, ...args) {
    context = context ? new Object(context) : window
    let key = Symbol()
    context[key] = this
    context[key](...args)
    delete context[key]
  }

  Function.prototype.myapply = function(context) {
    context = context || window
    let key = Symbol()
    let args = arguments[1]
    context[key] = this
    let result
    if (args) {
      result = context[key](...args)
    } else {
      result = context[key]()
    }
    delete context[key]
  }

  Function.prototype.mybind = function(context) {
    const self = this
    let args = arguments.slice(1)
    const bindFn = function() {
      return self.apply(
        this instanceof bindFn ? this : context,
        ...args,
        ...arguments
      )
    }

    bindFn.prototype = Object.create(self.prototype)

    return bindFn
  }

  //   new
  const createNew = (Con, ...args) => {
    const obj = Object.create(Con.prototype)
    // Object.setPrototypeOf(obj, Con.prototype)
    let result = Con.apply(obj, args)
    return result instanceof Object ? result : obj
  }

  //  instance
  const myInstanceOf = (left, right) => {
    let leftValue = left.__proto__
    let rightValue = right.prototype
    while (true) {
      if (leftValue === null) return false
      if (leftValue === rightValue) return true
      leftValue = leftValue.__proto__
    }
  }

  //   
  const deepClone = (target, cache = new WeakMap()) => {
    if (target === null || typeof target !== 'object') {
      return target
    }
    if (cache.get(target)) {
      return target
    }
    const copy = Array.isArray(target) ? [] : {}
    cache.set(target, copy)
    Object.keys(target).forEach(
      key => (copy[key] = deepClone(target[key], cache))
    )
    return copy
  }

  //  
  const debounce = (fn, wait = 300, leading = true) => {
    let timerId, result
    return function(...args) {
      timerId && clearTimeout(timerId)
      if (leading) {
        if (!timerId) {
          result = fn.apply(this, args)
          timerId = setTimeout(() => {
            timerId = null
          }, wait)
        }
      } else {
        timerId = setTimeout(() => {
          result = fn.apply(this, args)
          timerId = null
        }, wait)
      }
      return result
    }
  }

  //  -   
  const throttle = (fn, wait = 300) => {
    let timerId
    return function(...args) {
      if (timerId) {
        setTimeout(() => {
          return fn.apply(this, args)
          timerId = null
        }, wait)
      }
    }
  }

  //  -   
  const throttleByTimer = (fn, wait = 300) => {
    let prev = 0
    return function(...args) {
      let now = +new date()
      if (now - prev > wait) {
        prev = now
        return fn.apply(this, args)
      }
    }
  }

  //    
  const uniqBy = (arr, key) => {
    return [...new Map(arr.map(item => [item[key], item])).values()]
  }

  //     -   
  const flatten = arr =>
    arr
      .toString()
      .split(',')
      .map(item => +item)

  //     
  const flatten2 = (arr = [], deep = 1) => {
    return arr.reduce((cur, next) => {
      return Array.isArray(next) && deep > 1
        ? [...cur, ...flatten2(next, deep - 1)]
        : [...cur, next]
    }, [])
  }

  //     
  const currying = fn =>
    (_curry = (...args) =>
      args.length >= fn.length
        ? fn(...args)
        : (...newArgs) => _curry(...args, ...newArgs))

  //    
  class EventEmitter {
    subs = {}
    emit(event, ...args) {
      if (this.subs[event] && this.subs[event].length) {
        this.subs[event].forEach(cb => cb(...args))
      }
    }
    on(event, cb) {
      ;(this.subs[event] || (this.subs[event] = [])).push(cb)
    }
    off(event, offCb) {
      if (offCb) {
        if (this.subs[event] && this.subs[event].length)
          this.subs[event] = this.subs[event].filter(cb => cb !== offCb)
      } else {
        this.subs[event] = []
      }
    }
  }

좋은 웹페이지 즐겨찾기