JS高级——手写call()、apply()、bind()

0、call、apply、bind的区别

bind,call,apply的作用都是用来改变this指向的

  1. call方法
    call方法的第一个参数是this的指向
    后面传入的是一个参数列表(注意和apply传参的区别)。当一个参数为null或undefined的时候,函数中的this默认指向window(在浏览器中),和apply一样,call也只是临时改变一次this指向,并立即执行。

  2. apply方法:使用apply方法改变this指向后原函数会立即执行,且此方法只是临时改变thi指向一次。
    apply接受两个参数:
    第一个参数是this的指向
    第二个参数是函数接受的参数,以数组的形式传入,且当第一个参数为null、undefined的时候,函数中的this默认指向window(在浏览器中)

在这里插入图片描述
3. bind方法
bind方法和call很相似
第一参数也是this的指向
后面传入的也是一个参数列表(但是这个参数列表可以分多次传入,call则必须一次性传入所有参数),但是它改变this指向后不会立即执行,而是返回一个永久改变this指向的函数

在这里插入图片描述
在这里插入图片描述

一、call函数的实现

在这里插入图片描述

在这里插入图片描述

// 给所有的函数添加一个myCall方法
Function.prototype.myCall = function (thisArg, ...args) {
    // 1. 获取需要被执行的函数
    var fn = this
    // 对thisArg转成对象类型(防止它传入的是非对象类型的参数)
    thisArg = thisArg ? Object(thisArg) : window

    // 2.为调用myCall的函数绑定this(利用了js的隐式绑定)
    thisArg.fn = fn
    // 3.调用需要被执行的函数
    const result = thisArg.fn(...args)
    delete thisArg.fn
    // 4.将函数的调用结果返回
    return result
}

const result = sum.myCall('aaa', 10, 20)
console.log(result)

function sum(num1, num2) {
    console.log('sum函数被执行了', this)
    return num1 + num2
}

// const result = sum.call('aaa', 20, 30)
// console.log(result)

二、apply函数的实现

在这里插入图片描述

Function.prototype.myApply = function (thisArg, argArr) {
    // 1. 获取调用myApply的函数
    var fn = this
    // 2. 将thisArg转成对象类型,否则后续无法通过thisArg.fn绑定this,
    // 且若thisArg没有传值,则让this绑定为window
    thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window
    thisArg.fn = fn
    // 3. 对argArr进行处理,确保它有传值并且为数组,
    // 否则后续通过...argArr解构会报错:因为如果argArr不传值时为undefined,...undefined解构就会报错
    argArr = argArr ? argArr : []
    // 4. 执行函数
    const result = thisArg.fn(...argArr)
    delete thisArg.fn
    // 5. 将函数执行结果返回
    return result
}
function sum(num1, num2) {
    console.log(this, num1, num2)
    return num1 + num2
}
const result1 = sum.myApply('aaa', [10, 20])
console.log(result1)
const result2 = sum.myApply(0)
console.log(result2)
sum.apply('aaa', [10, 20])
sum.apply(0)

三、bind函数的实现

bind方法和call很相似
第一参数也是this的指向
后面传入的也是一个参数列表(但是这个参数列表可以分多次传入,call则必须一次性传入所有参数),但是它改变this指向后不会立即执行,而是返回一个永久改变this指向的函数
在这里插入图片描述
在这里插入图片描述

Function.prototype.myBind = function (thisArg, ...argArr) {
    // 1.获取道真实需要调用的函数
    var fn = this
    // 2.处理thisArg不传值的情况,不传值则默认函数里的this绑定window,传了值则还需要确保它为对象类型,否则后续thisArg.fn = fn会报错
    thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window
    var proxyFn = function (...args) {
        // 3.绑定this(这里用了js的隐式绑定)
        thisArg.fn = fn
        // 4.将函数传入的剩余参数进行合并,用于实现bind函数的第二个参数列表可以分多次传入
        const finalArgArr = [...argArr, ...args]
        // 5.调用函数
        const result = thisArg.fn(...finalArgArr)
        delete thisArg.fn
        // 6.将函数执行结果返回
        return result
    }
    return proxyFn
}
function sum(num1, num2) {
    console.log(this, num1, num2)
    return num1 + num2
}
const newSum = sum.myBind('aaa', 10, 20) // 参数列表可以分多次传入
const result = newSum(30, 40) // 参数列表可以分多次传入
console.log(result)

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值