bind,call,apply

  • 共同点:
    • 功能角度:三者都能改变 this 指向,且第一个传递的参数都是 this 指向的对象。
    • 传参角度:三者都采用的后续传参的形式。
  • 不同点:
    • 传参方面: call 的传参是单个传递(序列),而 apply 后续传递的参 数是数组形式。而 bind 与call相同。
    • 执行方面: call 和 apply 函数的执行是直接执行的,而 bind 函数会返回一个函数,然后我 们想要调用的时候才会执行。

call 模拟:

// this 为调用的函数
// context 是参数对象
Function.prototype._Call = function (context) {
    // 判断调用者是否为函数
    if (typeof this !== 'function') {
        throw new TypeError('Error')
    }
    // 不传参默认为 window
    context = context || window
    // 新增 fn 属性,将值设置为需要调用的函数
    context.fn = this
    // 将 arguments 转化为数组将 call 的传参提取出来 [...arguments]
    const args = Array.from(arguments).slice(1)
    // 传参调用函数
    const result = context.fn(...args)
    // 删除函数
    delete context.fn
    // 返回执行结果
    return result;
}

 

this为call的调用者 也就是 前者函数,也就是拿到调用者,将其赋给传入对象参数,对象参数调用,将this指向更改。

 

apply模拟

// 手写一个 apply 方法
Function.prototype._Apply = function (context) {
    // 判断调用者是否为函数
    if (typeof this !== 'function') {
        throw new TypeError('Error')
    }
    // 不传参默认为 window
    context = context || window
    // 新增 fn 属性,将值设置为需要调用的函数
    context.fn = this
    // 返回执行结果
    let result;
    // 判断是否有参数传入
    if (arguments[1]) {
        result = context.fn(...arguments[1])
    } else {
        result = context.fn()
    }
    // 删除函数
    delete context.fn
    // 返回执行结果
    return result;
}

bind函数

// 手写一个 bind 函数
Function.prototype._bind = function (context) {
    // 判断调用者是否为函数
    if (typeof this !== 'function') {
        throw new TypeError('Error')
    }
    // 截取传递的参数
    const args = Array.from(arguments).slice(1)
    // _this 指向调用的函数
    const _this = this;
    // 返回一个函数
    return function F() {
        // 因为返回了一个函数,我们可以 new F(),所以需要判断
        // 对于 new 的情况来说,不会被任何方式改变 this
        if (this instanceof F) {
            return new _this(...args, ...arguments)
        } else {
            return _this.apply(context, args.concat(...arguments))
        }
    }
}
// 普通函数
function test() {
    // new 的方式调用 bind 参数输出换做 [...arguments]
    console.log(this.name);
}

 

上一篇:【Beat】Scrum Meeting 4


下一篇:ES6箭头函数声明特点