前端日常记录

59 阅读1分钟

前端手写练习

PromiseDeepcopydebouncethrottleEventEmittercall\bind\apply
异步深拷贝防抖节流发布订阅this绑定
  1. 手写Promise
    class Promise{
        constructor(callback){
            this.status = 'pending';
            this.answer = undefined;
            this.succeArr = [];
            this.failArr = [];
            this.resolve = (val)=>{
                if(this.status === 'fullfiled') {
                    this.status === 'fullfiled';
                    this.answer = val;
                    this.succeArr.map(item=>item())
                }
            };

            this.reject = (val)=>{
                if(this.status === 'reject') {
                    this.status === 'reject'
                    this.answer = val
                    this.failArr.map(item=>item())
                }
            };

            try{
                callback(this.resolve.bind(this),this.reject.bind(this))
            } catch(err) {
                this.reject(err)
            }
        }
        then(suc,fail){
            if(this.status === 'fullfiled') {
                suc(this.answer);
            }
            if(this.status === 'reject') {
                fail(this.answer);
            }
            if(this.status === 'pending') {
                this.succeArr.push(()=>suc(this.answer))
                this.failArr.push(()=>fail(this.answer))
            }
        }
        all(promiseArr){
            let index = 0;
            let data = []
            return new Promise((resolve,reject)=>{
                for (const i in promiseArr) {
                    let promise = promiseArr[i];
                    index++;
                    promise().then(res=>{
                        data[i] = res
                        if(index===promiseArr.length){
                            resolve(data)
                        }
                    }).catch(err=>{
                        reject(err)
                    })
                }
            })
        }
    }
  1. 手写深拷贝
function deepcopy(obj,hash= new WeakMap()) {
    if(obj!==null||typeof obj !== 'Object'){
        return obj
    }
    // var res = Array.isArray(obj)?[]:{};
    if(hash.get(obj)) return hash.get(obj)
    let cloneObj = new obj.construtor()
    hash.set(obj,cloneObj)
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            const element = obj[key];
            cloneObj[key] = deepcopy(element,hash)
        }
    }
    return cloneObj
}
  1. 防抖
function debounce(func,delay){
  let timer;
  return function() {
    if(timer){
      clearTimeout(timer)
    } 
    setTimeout(()=>{
      timer = func()
    },delay)
  }
}
  1. 节流
function throttle(fn,delay) {
  let flag = true;
  return ()=>{
    if(!flag) return
    setTimeout(() => {
      if(flag) {
        fn()
        flag = false
      }
    }, delay);
  }
}
  1. 发布订阅
class EventEmitter {
  public event:any

  constructor(){
    this.event={}
  }

  addListener(type,callback){
    if(!this.event[type]){
      this.event[type]=[callback]
    }else{
      this.event[type].push(callback)
    }
  }

  removeListener(type,callback){
    if(this.event[type]){
      this.event[type]=this.event[type].filter(item=>item!==callback)
    }else{
      return
    }
  }

  emit(type,params){
    this.event[type]&&this.event[type].forEach((fn) => fn.apply(this, params))
  }

  once(type,callback){
    function onceFn(params) {
      callback();
      this.removeListener(type,onceFn)
    }
    this.addListener(type,onceFn)
  }
}
  1. call\bind\apply
Function.protoType.call=function(obj,arg){
    let ctx =  obj || window
    let symbKey = symbol();
    ctx[symbKey] = this;
    let res = ctx[symbKey](...arg);
    delete ctx[symbKey];
    return res
}
// let obj = { c:2 }
// let func = function(b){ this.c+b };  //{c:2,symKey:func}
// func.call(obj,3);
Function.protoType.bind=function(){
    let instance = (context===null ? window : this)  // const [instance,context,params] =[this, context, arr]
    return function(){                               
      return instance.call(context,...params)       // return instance.call(context,...params)
    }
}

Function.protoType.apply=function(context,args=[]){
    let cxt = context || window;
    const specialKey = Symbol();
    cxt[specialKey] = this;
    let result = args.length>0? cxt[specialKey](...args):cxt[specialKey]();
    delete cxt[specialKey];
    return result;
}