手写bind/call/apply/new/防抖/节流

1,307 阅读2分钟

手写bind

  • 第一个参数接收 this 对象
  • 返回函数,根据使用方式
    • 直接调用
      • 改变 this 指向
      • 拼接参数
      • 调用函数
    • 构造函数
      • 不改变 this 指向,忽略第一参数
      • 拼接参数
      • new 函数

Function.prototype.myBind = function(_this, ...args) {
        const fn = this
        return function F(...args2) {
                return this instanceof F ? new fn(...args, ...args2)
                : fn.apply(_this, args.concat(args2))
        }
}
//使用
function Sum (a, b) {
        this.v= (this.v || 0)+ a + b
        returnthis
}
const NewSum = Sum.myBind({v: 1}, 2)
NewSum(3) // 调用:{v: 6}
new NewSum(3) // 构造函数:{v: 5} 忽略 myBind 绑定this

手写call

  • 第一参数接收 this 对象
  • 改变 this 指向:将函数作为传入 this 对象的方法
  • 展开语法,支持传入和调用参数列表
  • 调用并删除方法,返回结果

Function.prototype.myCall = function(_this, ...args) {
        if (!_this) _this = Object.create(null)
        _this.fn = this
        const res = _this.fn(...args)
        delete _this.fn
        return res
}
// 使用
function sum (a, b) {
        return this.v + a + b
}
sum.myCall({v: 1}, 2, 3) // 6

手写apply

  • 第一参数接收 this 对象
  • 改变 this 指向:将函数作为传入 this 对象的方法
  • 第二个参数默认数组
  • 展开语法,支持调用参数列表
  • 调用并删除方法,返回结果

Function.prototype.myApply = function(_this, args = []) {
        if (!_this) _this = Object.create(null)
        _this.fn =this
        const res = _this.fn(...args)
        delete _this.fn
        return res
}
// 使用
function sum (a, b) {
        return this.v + a + b
}
sum.myApply({v: 1}, [2, 3]) // 6

手写new

  • 第一参数作为构造函数,其余参数作为构造函数参数
  • 继承构造函数原型创建新对象
  • 执行构造函数
  • 结果为对象,返回结果,反之,返回新对象

function myNew(...args) {
        const Constructor = args[0]
        const o = Object.create(Constructor.prototype)
        const res = Constructor.apply(o, args.slice(1))
        return res instanceof Object ? res : o
}
// 使用
function P(v) {
        this.v = v
}
const p = myNew(P, 1) // P {v: 1}

手写防抖

  • 声明定时器
  • 返回函数
  • 一定时间间隔,执行回调函数
  • 回调函数
    • 已执行:清空定时器
    • 未执行:重置定时器

function debounce(fn, delay) {
        let timer = null
        return function (...args) {
                if (timer) clearTimeout(timer)
                timer = setTimeout(() => {
                        timer = null
                        fn.apply(this, args)
                }, (delay + '') | 0 || 1000 / 60)
        }
}

手写节流

  • 声明定时器
  • 返回函数
  • 一定时间间隔,执行回调函数
  • 回调函数
    • 已执行:清空定时器
    • 未执行:返回

function throttle(fn, interval) {
        let timer = null
        return function (...args) {
                if (timer) return
                timer = setTimeout(() => {
                        timer = null
                        fn.apply(this, args)
                }, (interval +'')| 0 || 1000 / 60)
        }
}