js函数实现

356 阅读2分钟
// 函数柯里化(思路:递归收集参数,参数刚好时调用原函数)
function curry(fn, args = []){
  
  return (...arg) => {
    let _arg = args.concat(arg)
    if(_arg.length != fn.length){
      return curry(fn, _arg)
    }else{
      return fn(..._arg)
    }
  }
}
// 节流
function throttle(fn, delay){
  let timer;
  return () => {
    if(timer){
      return
    }
    timer = setTimeout(() => {
      fn()
      timer = null
    }, delay)
  }
}
// 防抖
function debounce(fn, delay){
  let timer;
  return () => {
    if(timer){
       clearTimeout(timer)
    }
    timer = setTimeout(() => {
      fn()
    }, delay)
  }
}
// call
function mycall(that, ...args){
  that = that == null ? window : new Object(that)
  that.fn = this;
  that.fn(...args);
  delete that.fn;
}
Function.prototype.mycall = mycall
// apply
function myapply(that, args){
  that = that == null ? window : new Object(that)
  that.fn = this;
  that.fn(...args);
  delete that.fn;
}
Function.prototype.myapply = myapply
// 数组转树
const currentArray = [
  {id:"01", name: "张大大", pid:"", job: "项目经理"},
  {id:"02", name: "小亮", pid:"01", job: "产品leader"},
  {id:"03", name: "小美", pid:"01", job: "UIleader"},
  {id:"04", name: "老马", pid:"01", job: "技术leader"},
  {id:"05", name: "老王", pid:"01", job: "测试leader"},
  {id:"06", name: "老李", pid:"01", job: "运维leader"},
  {id:"07", name: "小丽", pid:"02", job: "产品经理"},
  {id:"08", name: "大光", pid:"02", job: "产品经理"},
  {id:"09", name: "小高", pid:"03", job: "UI设计师"},
  {id:"10", name: "小刘", pid:"04", job: "前端工程师"},
  {id:"11", name: "小华", pid:"04", job: "后端工程师"},
  {id:"12", name: "小李", pid:"04", job: "后端工程师"},
  {id:"13", name: "小赵", pid:"05", job: "测试工程师"},
  {id:"14", name: "小强", pid:"05", job: "测试工程师"},
  {id:"15", name: "小涛", pid:"06", job: "运维工程师"}
];

function arrToTree(list, pid){
  let children = list.filter(item => item.pid == pid);
  return children.map(item => {
    item.children = arrToTree(list, item.id);
    return item;
  })
}
// instanceof实现
function instanceOf(origin, target) {
      
    while(1){
       if(origin.__proto__ == target.prototype){
         return true
       } 
       if(origin.__proto__ == null){
         return false
       }
      origin = origin.__proto__
    }
}
// promise(丑陋的)
class UglyPromise {
  constructor(callback){
    this.status = 'pending'
    this.value = undefined
    this.sucessCb = []
    this.failedCb = []
   
    const resolve = value => {
      if(this.status === 'pending'){
        this.status = 'success'
        this.value = value
        this.sucessCb.forEach(fn => {
          fn(value)
        })
      }
    }
    
    const reject = value => {
      if(this.status === 'pending'){
        this.status = 'failed'
        this.value = value
        this.failedCb.forEach(fn => {
          fn(value)
        })
      }
    }
   
    try {
      callback(resolve, reject)
    } catch(e) {
      reject(e)
    }
  }
 
  then(successCb, failedCb){
    
    if(typeof successCb === 'function'){
      if(this.status == 'pending'){
        this.sucessCb.push(successCb)
      }else{
        successCb(this.value)
      }
    }
    if(typeof failedCb === 'function'){
      
      if(this.status == 'pending'){
        this.failedCb.push(failedCb)
      }else{
        failedCb(this.value)
      }
    }
    
    return this
  }
  
  catch(failedCb){
    if(typeof failedCb === 'function'){
      if(this.status == 'pending'){
        this.failedCb.push(failedCb)
      }else{
        failedCb(this.value)
      }
    }
  }
  
}

UglyPromise.resolve = value =>{
    return new UglyPromise(rev => {
      rev(value)
    })
}

UglyPromise.race = arr =>{
    return new MyPromise((rev,rej) => {
      for(let i = 0;i < arr.length;i++){
        arr[i].then(res => {
          rev(res)
        }).catch(e => {
          rej(e)
        })
      }
    })
}

UglyPromise.all = arr =>{
    let length = arr.length;
    let count = 0;
    let result = new Array(length);
    if(length == 0){
        return UglyPromise.resolve()
    }
    return new UglyPromise((rev,rej) => {
      for(let i = 0;i<arr.length;i++){
        arr[i].then(res => {
          result[i] = res // 为了结果顺序与开始顺序一致
          if(++count == length){
            rev(result)
          }
        }).catch(e => {
          rej(e)
        })
      }
    })
}