小笔记(常见手写代码题)

80 阅读1分钟

手写 new

function myNew(fn, ...args) {
  let obj = Object.create(fn.prototype);
  let res = fn.apply(obj, args);
  if (res && ['function', 'object'].includes(typeof res) {
    return res;
  }
  
  return obj;
}

手写 call

Function.prototype.myCall = function(context, ...args) {
  if (!content || context === null) {
    context = window;
  }
  
  let fn = symbol();
  context[fn] = this;
  
  return context[fn](...args);
}

手写 apply

Function.prototype.myApply = function(context, args) {
  if (!content || context === null) {
    context = window;
  }
  
  let fn = symbol();
  context[fn] = this;
  
  return context[fn](...args);
}

手写 bind

传统使用 bind方法,返回的是一个函数,需要等待后续的调用

Function.prototype.myBind = function(context, ...args) {
  let fn = symbol();
  context[fn] = this;
  let _this = this;
  
  const result = function(...innerArgs) {
    //兼容 new构建
    if (this instanceof _this) {
      this[fn] = _this;
      this[fn](...[...args, ...innerArgs]);
    }
    else {
      context[fn](...[...args, ...innerArgs]);
    }
  }
  result.prototype = Object.create(this.prototype);
  return result;
}

手写实现数组扁平化

//使用while循环
while(arr.some(a => Array.isArray(a))) {
  arr = [].concat(...arr);
}

//使用传统的flat函数
arr.flat(Infinity)

//使用reduce实现
function _flat(arr) {
  return arr.reduce(
    (pre, cur) => pre.concat(Array.isArray(cur) ? _flat(cur) : cur) , 
    []
  )
}

手写 setTimeout模拟 setInterval

function myInterval(fn, t) {
  let timer;
  function interval() {
    //先执行方法
    fn();
    timer = setTimeout(interval, t);
  }
  
  interval();
  
  return {
    cancel: () => clearTimeout(timer);
  }
}

手写防抖

function debounce(fn, wait) {
  let timer;
  return function(...args) {
    const ctx = this;
    if (timer) {
      clearSetTimeout(timer);
      timer = undefined;
    }
    
    timer = setTimeout(() => {
      fn.apply(ctx, args);
    }, wait)
  }
}

手写节流

function throttle(fn, gap) {
  let curTime = Date.now();
  return function(...args) {
    let nowTime = Date.now();
    const ctx = this;
    if (nowTime - curTime >= gap) {
      curTime = Date.now();
      return fn.apply(ctx, args);
    }
  }
}

手写深拷贝

function isObject(val) {
  return typeof val === 'object' && val !== null;
}

function deep(obj) {
  //如果不是对象类型
  if (!isObject(obj)) return obj;
  let target = Array.isArray(obj) ? [] : {};
  Reflect.ownkeys(obj).forEach((item) => {
    if (isObject(obj[item])){
      target[item] = deep(obj[item])
    }
    else {
      target[item] = obj[item];
    }
  })
  
  return target;
}

手写 发布订阅

class EventEmitter {
  constructor() {
    this.events = {}
  }
  
  //订阅
  on(type, cb) {
    if (!this.events[type]) {
      this.events[type] = [];
    }
    
    this.events[type].push(cb);
  }
  
  //删除
  off(type, cb) {
    if (!this.events[type]) return;
    this.events[type] = this.events[type].filter(i => i !== cb);
  }
  
  //发布
  emit(type, ...args) {
    if (!this.events[type]) return;
    this.events[type].forEach(fn => fn.apply(this, args))
  }
}