通俗易懂的给你讲解 call / apply / bind 的实现

简介: call / apply / bind 的实现

e7751a43b091e93fe72b5194a726c6e.png

前言

javascriptcall / apply / bind 这三个方法是日常工作中比较实用的改变函数 this 指向的方法,很方便,但由于涉及到对 this 的理解,同时也是很容易出错的方法,也是面试官喜欢问的考题之一,今天就和大家一起好好聊一聊这三个方法

call / apply / bind 的区别

我们先简单的过一下他们之间的异同点,有个简单概念之后再详细分析

共同点

他们的功能一致,都是用来改变函数this 指向

// 语法
函数.call(thisArg, arg1, arg2, ...)  
函数.apply(thisArg, [argsArray])
函数.bind(thisArg, [argsArray])  
复制代码

不同点

  • call / apply 可以立即执行;bind 不会立即执行,而是返回一个函数,可以在需要的时候再执行
  • 参数不同:apply 第二个参数是数组;call 和 bind 有多个参数需要用逗号隔开挨个写

简单应用场景

  • 改写 this 指向,让目标对象使用一些方法
const person = {
    name: '江',
    say: function () {
        console.log(this.name)
    }
}
person.say()    // 江
const obj = {
    name: '李'
}
person.say.call(obj)    // 李
person.say.apply(obj)   // 李
person.say.bind(obj)()  // 李
复制代码
  • 借用方法
const numbers = [5, 458 , 120 , -215 ]; 
const maxInNumbers = Math.max.apply(Math, numbers),   //458
      maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458
复制代码

number 本身没有 max 方法,但是 Math 有,我们就可以借助 call 或者 apply 使用其方法

手写 call

Function.prototype.myCall = function (thisArg, ...argsArray) {
    // 判断 thisArg 是否 null / undefine
    if (thisArg === null || thisArg === undefined) {
        thisArg = window
    }
    console.log(this) // 这里的 this 是调用的函数
    thisArg.fn = this
    thisArg.fn(...argsArray)
}
复制代码

手写 apply

Function.prototype.myApply = function (thisArg, argsArray) {
    // 判断 thisArg 是否 null / undefine
    if (thisArg === null || thisArg === undefined) {
        thisArg = window
    }
    console.log(this) // 这里的 this 是调用的函数
    thisArg.fn = this
    thisArg.fn(...argsArray)
}
复制代码

手写 bind

Function.prototype.myBind = function (thisArg, argsArray) {
    // 判断 thisArg 是否 null / undefine
    if (thisArg === null || thisArg === undefined) {
        thisArg = window
    }
    console.log(this) // 这里的 this 是调用的函数
    thisArg.fn = this
    return function () {
        thisArg.fn(...argsArray)
    }
}
复制代码

使用一下我们手写的三个方法,看是否满足我们的要求

const person = {
    name: '江',
    say: function (word) {
        console.log(this.name + ":" + word)
    }
}
person.say('你好')    // 江:你好
const obj = {
    name: '李'
}
person.say.myCall(obj, 'hello')         // 李:hello
person.say.myCall(obj, ['hello'])       // 李:hello
person.say.myBind(obj, ['hello'])()     // 李:hello
复制代码

可以看到可以按期望输出结果了~

总结

对于改写 this 指向的实现,关键点是要理解:

  • 我们自定义的方法,必须是挂载在 Function 这个个构造函数上的,这是一个大前提,因为只有这样,我们在任意方法上使用 . 才能找到我们的方法属性(其实就是原型链
  • 还有就是对当前函数里 this 的理解,这个场景可以简单理解为 this 是谁调用就指向谁,那么
    函数.myCall() 就很清晰了,是函数调用了 myCall,所以 myCall 方法里的 this 指向的就是函数
  • 理解了以上两点,就只要把 this(想执行的方法) 挂到我们的目标对象thisArg上面就可以了
相关文章
new bind apply call instanceof 等笔记
new bind apply call instanceof 等笔记
37 0
|
23天前
|
JavaScript 前端开发 开发者
call、bind、apply区别
【10月更文挑战第26天】`call`、`bind` 和 `apply` 方法在改变函数 `this` 指向和参数传递方面各有特点,开发者可以根据具体的需求和使用场景选择合适的方法来实现更灵活和高效的JavaScript编程。
27 1
|
4月前
|
JavaScript 前端开发 测试技术
手写call , apply , bind 方法的实现
本文通过实例讲解了JavaScript中`call`、`apply`及`bind`方法的用途与实现。以`call`为例,展示了如何改变函数内的`this`指向,并立即执行该函数。通过在`Function.prototype`上定义`myCall`,利用`Symbol`确保新增属性的唯一性,从而避免命名冲突。接着介绍了如何处理不定数量的参数传递,最终实现了自定义的`myCall`方法。随后简述了`apply`与`call`的区别,并展示了其实现方式,主要在于参数传递形式的不同。最后,通过`bind`方法创建了一个返回新函数的例子,该新函数具有固定的`this`上下文,同时支持分批参数传递。
35 2
手写call , apply , bind 方法的实现
|
JavaScript 前端开发
面试官: call、apply和 bind有什么区别?
面试官: call、apply和 bind有什么区别?
bind、call、apply 区别
bind、call、apply 区别
78 0
手写call-apply-bind以及了解柯里化
手写call-apply-bind以及了解柯里化
call、apply、bind笔记
call、apply、bind笔记
63 0
|
前端开发
前端学习案例1:apply,call,bind使用1
前端学习案例1:apply,call,bind使用1
82 0
前端学习案例1:apply,call,bind使用1
|
前端开发
前端学习案例2:apply,call,bind使用2
前端学习案例2:apply,call,bind使用2
74 0
前端学习案例2:apply,call,bind使用2