通俗易懂的给你讲解 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上面就可以了
目录
打赏
0
0
0
0
2
分享
相关文章
VUE3(二十三)自定义分页组件Pagination
刚开始使用vue3写博客的时候,其相关配套的UI库并没有正式发布,但是我还要用,所以这里我自定义了一个分页组件。
734 0
VUE3(二十三)自定义分页组件Pagination
系列文章深度解读|SwiftUI 背后那些事儿
前言 今年苹果的WWDC你看了吗?苹果在2019年的WWDC的重头戏当然非SwiftUI莫属:全新的声明式语法、绑定式API、和响应式变成框架Combine。这一切的一切都预示着即将在Apple Native布局系统掀起一场革命。
17899 0
通义万相AI绘画创作方案:创新艺术的数字化画布
在数字化艺术创作的浪潮中,通义万相AI绘画创作方案以其强大的图像生成能力,为艺术家和设计师提供了一个全新的创作平台。本文将从部署体验、功能亮点、用户反馈以及改进建议等方面,全面评测这一创新方案。
解决报错Exception encountered during context initialization
程序员不是在去生产bug的路上,那就是在去解决bug的路上。
228 1
分布式机器学习系统:设计原理、优化策略与实践经验
本文详细探讨了分布式机器学习系统的发展现状与挑战,重点分析了数据并行、模型并行等核心训练范式,以及参数服务器、优化器等关键组件的设计与实现。文章还深入讨论了混合精度训练、梯度累积、ZeRO优化器等高级特性,旨在提供一套全面的技术解决方案,以应对超大规模模型训练中的计算、存储及通信挑战。
379 4
中草药管理与推荐系统Python+Django网页界面+推荐算法+计算机课设系统+网站开发
中草药管理与推荐系统。本系统使用Python作为主要开发语言,前端使用HTML,CSS,BootStrap等技术和框架搭建前端界面,后端使用Django框架处理应用请求,使用Ajax等技术实现前后端的数据通信。实现了一个综合性的中草药管理与推荐平台。具体功能如下: - 系统分为普通用户和管理员两个角色 - 普通用户可以登录,注册、查看物品信息、收藏物品、发布评论、编辑个人信息、柱状图饼状图可视化物品信息、并依据用户注册时选择的标签进行推荐 和 根据用户对物品的评分 使用协同过滤推荐算法进行推荐 - 管理员可以在后台对用户和物品信息进行管理编辑
392 12
中草药管理与推荐系统Python+Django网页界面+推荐算法+计算机课设系统+网站开发
从零开始的PICO教程(4)--- UI界面绘制与响应事件
这篇文章是PICO开发系列教程的第四部分,主要介绍了如何在PICO 4 VR环境中创建UI界面,包括Canvas和Panel的配置、UI元素的绘制、以及Button和Slider的事件响应绑定,并通过示例展示了数字增减和滑块功能的具体实现。
从零开始的PICO教程(4)--- UI界面绘制与响应事件
人工智能|ReACT 推理提示
**ReAct框架概览** ReAct融合推理与行动,提LLM性能: - 引入心理状态表达,强化答案质量。 - 多步思维,反馈循环优化决策。 应用场景拓展至智能助手,医疗等。 LangChain,ChatGPT工具实践ReAct。 后续深入学习,实战企业AI助理开发。 (225/240 characters)
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等