笔记13常见js手写题(1)

常见js手写题1



函数防抖、函数节流、函数柯里化、二分查找、InstanceOf、call、apply,bind



函数防抖

  function debounce(fn,wait){ //防抖:每次点击重置定时器
    let timer = null
    return (...arg)=>{
      let self = this
      clearTimeout(timer)
      timer = setTimeout(()=>{
        fn.apply(self,arg)
      },wait)
    }
  }

函数节流
  function throttle(fn,wait){ //节流:规定时延内重复作用无效
    let flag = false
    return (...arg)=>{
      let self = this 
      if(flag){retun}
      flag = true;
      setTimeout(()=>{
        fn.apply(self,arg)
      },wait)
    }
  }

函数柯里化
function curry(fn,arg=[]){ //传入一个函数,返回一个函数
    let length = fn.length
    return (...rest)=>{
      let _arg = arg.slice(0) //获得现有参数数组深拷贝副本
      _arg.push(...rest) //将函数参数传入现存参数数组
      if(length > _arg.length){
        return curry.call(this,fn,_arg) //参数未传够则递归
      } else {
        fn.apply(this,_arg)      }
  }
}

二分查找
  function binarySearch(arr,target){ //输入数字,目标;返回找到的下标
    let left =0,
        right =arr.length-1,
        mid;
    while(left < right){
      mid =Math.floor((left+right)/2);
      if(target > arr[mid]){
        left = mid+1
      }
      else if (targrt < arr[mid]){
        right = mid-1
      }
      else {
        return mid
      }
    }    
  } 

InstanceOf实现
  InstanceOf = (A,B)=>{  //A:需判定的子类;B:父类
    let a = A.__proto__;
    let b = B.prototype;
    while(true){
      if(a === b){ return true } //原型继承条件:子类隐式原型指向父类显示原型
      if(a === null){return false}
      a = a.__proto__
    }
  }

call实现

call、apply修改函数作用域立即执行;不同的是apply接收一个参数数组
    Function.prototype.myCall = function(context,...args){
    context = context || window //修改当前上下文的指向
    //let fn = Symbol('fn') //保证fn为一个全局唯一的值
    context.fn = this 
    let res = eval('context.fn(...args)')
    delete context.fn //fn是context的属性,调用后删除
    return res
  }

    //定义用与call的函数和this需要指向的对象
    function test (a,b){
      console.log(a,b,'say',this.words?this.words:'---')
    }
    let obj = { words:'hello' }

    //执行
    test.myCall(obj,'Alice','Bob')

apply实现
    Function.prototype.myApply = function(context,args){
    context = context || window //修改当前上下文的指向
    context.fn = this 
    let res = eval('context.fn(...args)')
    delete context.fn //fn是context的属性,调用后删除
    return res
  }

    //定义用与apply的函数和this需要指向的对象
    function test (a,b){
      console.log(a,b,'say',this.words?this.words:'---')
    }
    let obj = { words:'hello' }

    //执行
    test.myApply(obj,['Alice','Bob'])  

bind实现

bind返回一个闭包函数,通过再次调用来执行
    Function.prototype.myBind = function(context,...args){
    context = context || window //修改当前上下文的指向
    context.fn = this 
    return (...rest)=>{
       context.fn(...args,...rest)
      }
    }


    //定义用与bind的函数和this需要指向的对象

    let bindObj={
      value : 5
    }
    let bindFn = function(a,b,c){
      console.log(this.value, a, b, c)
    }

    //执行bind函数,返回一个闭包,再次调用执行
    let res = bindFn.myBind(bindObj,1,2)  //绑定函数的调用对象为bindObj
    res(3)  //执行并还可传参数