bind函数简易实现

91 阅读1分钟

bind、call、apply 都是用来改变this指向,有所不同的是bind返回的是创建新函数,而不是和call、apply一样去执行调用原本的函数

bind函数的特点:

  1. 改变this指向
  2. 新函数的this是bind函数的第一个参数,其余参数则作为新函数的参数
  3. 改变this指向后,返回值没有变
  4. 在函数的原型上

实现bind函数:

  • 返回一个新的函数
Function.prototype.myBind = functtion () {
    // 返回新函数
    return function () {
        // 代码块
    }
}
  • 将函数的this指向为传进来的第一个参数,并且把剩余的参数保存并返回
let obj = {
    name: 'Rose',
    gender: 'female'
}

// bind函数
Function.prototype.myBind = function (context) {
    // 将原来的this保存,保证返回值不变
    const _this = this 
    // 将参数列表转化为数组,除去第一个参数
    let args = Array.from(arguments).slice(1)
    // 返回新函数
    return function () {
    // 利用apply将this指向context,参数进行拼接
    _this.apply(context, args.concat(Array.from(arguments)))
    }
}

// 声明一个函数
function fn(a, b, c) {
    console.log('函数内部this指向:', this)
    console.log('参数列表:', a, b, c)
}

let newFn = fn.myBind(obj, 1, 2)
newFn('myBind构造函数')
Snipaste_2023-07-11_22-47-22.png - 通过使用构造函数的方式执行,使函数内部的this执行会作为一个新的引用指向fn
let obj = {
    name: 'Rose',
    gender: 'female'
}

// bind函数
Function.prototype.myBind = function (context) {
    // 将原来的this保存,保证返回值不变
    const _this = this 
    // 将参数列表转化为数组,除去第一个参数
    let args = Array.from(arguments).slice(1)
    // 返回新函数
    let fn = function () {
        // 如果被new调用,this应该是fn的实例
        return _this.apply(
            this instanceof fn ? this : context || window, 
            args.concat(Array.from(arguments))
        )
    }
    // 维护fn的原型
    let temp = function () {}
    temp.prototype = _this.prototype
    // new的过程继承temp原型
    fn.prototype = new temp() 
    return fn
}

// 声明一个函数
function fn(a, b, c) {
    console.log('函数内部this指向:', this)
    console.log('参数列表:', a, b, c)
}

let newFn = fn.myBind(obj, 1, 2)
new newFn('myBind构造函数')

Snipaste_2023-07-11_22-59-28.png