当前位置: 首页 > news >正文

JS手写章节(1)—手写实现call、apply、bind

一、JS-call-apply-bind函数的基本使用

前言

在我们平常使用JS进行开发的过程中,有时会为某个函数的this的指向而苦恼,可能会因为拿不到想要的this而导致程序错误,为了解决这一问题,首先我们可以了解清楚this的四个绑定问题,即默认绑定,隐式绑定,显示绑定和new绑定,之前写过文章说过,懂了这个之后,我们可以判断清楚this的指向,而我们今天要说的即为显示绑定,直接使用call、apply、bind函数来粗暴的给想要的函数绑定我们给定的this。

1、call函数的基本使用

call函数是我们使用的比较多的函数,我们可以利用它来绑定this的值,call函数调用时候第一个参数要求我们传入要绑定的this,后面的参数要求我们传入函数的参数以逗号分隔,注意在调用call函数时候,原函数会直接执行一次。例如:
在这里插入图片描述

2、apply函数的基本使用

apply函数和call函数类似,唯一不同的是要求我们传递参数时候,以数组的形式传入,第一个参数依旧是我们需要绑定的this的值,注意调用apply函数时候,原函数也会立即执行
在这里插入图片描述
可以看出,与call调用得到的结果一样,其实我们可以利用apply函数参数是以数组形式传入的特点,配合扩展运算符,直接将参数以数组方式传递进去。
在这里插入图片描述

3、bind函数的基本使用

bind函数和call函数类似,传递的参数方式都是一样的,不一样的是bind函数调用不会立即执行,而会返回一个绑定了新的this的新函数。
在这里插入图片描述

我们可以看出,单纯调用bind函数没有任何反应,因为他不会立马执行,而是会返回一个绑定了新this的新函数。
在这里插入图片描述
图中可以看出,bind返回了一个新函数,参数即为在bind调用时传递的参数,如果bind调用时没有传递足够的参数,在返回的新函数中也可以传递参数,相当于放在原参数后面。

二、JS-函数的手写

前言

懂得了基本用法,我们可以自己使用一个call、apply、bind函数实行同样的效果。

1、call函数的手写

首先,我们知道call函数是所有function都可以调用的,因此我们可以在Function的原型对象上添加我们要实现的call函数,起名为cyj_call,即Function.prototype.cyj_call = function(thisArg,…argArray){},其次我们考虑如何将我们函数的this绑定到thisArg上?我们可以巧妙的使用使用this绑定规则中的隐式绑定,即thisArg.fn = fn;,这样我们的fn函数的this就指向thisArg了,那么还有一个问题,我们如何获取要原函数呢,还是用到了隐式绑定,我们要使用的时候肯定是类似这种使用方式的,fn.cyj_call(),那么这个时候由于cyj_call函数被fn调用,那么cyj_call函数里面的this便会隐式绑定到fn中,这时候我们在cyj_call函数里面的this就可以拿到原函数了,要注意的是我们可能绑定的this是一个字符串,那么这时候我们执行thisArg.fn = fn是报错的,因为字符串是不允许在上面添加fn属性的,我们可以执行Object(thisArg),这样便可以添加fn属性了,具体代码如下:

Function.prototype.cyj_call = function(thisArg, ...argArray) {
    thisArg = thisArg != undefined && thisArg != null ? Object(thisArg) : window;
    let fn = this;
    thisArg.fn = fn;
    let res = thisArg.fn(...argArray);
    delete thisArg.fn;
    return res;
};

在这里插入图片描述

2、apply函数的手写

apply函数的实现同理,只是在传递参数时候有些变化而已,通过call的手写,我们不难写出如下代码:

Function.prototype.cyj_bind = function(thisArg, argArray) {
    let fn = this;
    thisArg = thisArg != undefined && thisArg != null ? Object(thisArg) : window;
    argArray = argArray ? argArray : [];
    thisArg.fn = fn;
    let result = thisArg.fn(...argArray);
    delete thisArg.fn;
    return result;
};

在这里插入图片描述

3、bind函数的手写

bind函数的手写有些许不同,需要返回一个函数,并且返回的函数接受的参数要和bind调用时候的参数合在一起,传入原函数进行执行,然后返回结果。
不难写出以下代码:

Function.prototype.cyj_bind = function(thisArg, ...argArray) {
    thisArg = thisArg != undefined && thisArg != null ? Object(thisArg) : window;
    let fn = this;
    thisArg.fn = fn;
    return function(...args) {
        let res = thisArg.fn(...argArray, ...args);
        delete thisArg.fn;
        return res;
    };
};

在这里插入图片描述

三、结语

以上就是对JS中的call、apply、bind的手写实现,难度虽然不大,但是还是有些细节需要注意的,以上是我仓促写的代码,可能会有些没测试到的bug,但是总体来说应该没啥问题。以上就是JS-手写章节的第一篇,下一篇是手写实现Vue响应式原理,有问题欢迎私信!

相关文章:

  • 零基础小白学Node-RED(04):仪表板
  • 【正点原子I.MX6U-MINI应用篇】2、点亮开发板的LED
  • 【C++】第五章 数组:一维数组/二维数组
  • 阿里云大数据开发一面面经,已过,面试题已配答案
  • 自定义模块和第三方模块,cnmp
  • 【正点原子I.MX6U-MINI应用篇】3、Framebuffer应用编程,操作屏幕
  • 区间预测 | MATLAB实现GRU门控循环单元分位数回归多输入单输出
  • 大学网上课程查题系统搭建使用-公众号使用
  • 若依前后端分离版入门
  • DRV8812芯片被国产激光打印机驱动芯片TMI8262取代
  • 三十三、《大数据项目实战之用户行为分析》Spark SQL读写MySQL
  • 负载开关、高侧开关、低侧开关等
  • 【LeetCode】146、LRU 缓存【中等】
  • 【JavaWeb项目】基于WebSocket的Web聊天室
  • File对象转MultipartFile 如何new出高仿MultipartFile对象
  • centos安装java运行环境jdk+tomcat
  • co模块的前端实现
  • Iterator 和 for...of 循环
  • js ES6 求数组的交集,并集,还有差集
  • PHP变量
  • Python爬虫--- 1.3 BS4库的解析器
  • scrapy学习之路4(itemloder的使用)
  • Shadow DOM 内部构造及如何构建独立组件
  • Travix是如何部署应用程序到Kubernetes上的
  • Vue 动态创建 component
  • 如何解决微信端直接跳WAP端
  • 实现菜单下拉伸展折叠效果demo
  • 实战|智能家居行业移动应用性能分析
  • 用 Swift 编写面向协议的视图
  • 回归生活:清理微信公众号
  • 如何用纯 CSS 创作一个货车 loader
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • !$boo在php中什么意思,php前戏
  • # C++之functional库用法整理
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • #HarmonyOS:基础语法
  • #Linux(make工具和makefile文件以及makefile语法)
  • #数据结构 笔记三
  • $.each()与$(selector).each()
  • (1)(1.9) MSP (version 4.2)
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (10)ATF MMU转换表
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (4)事件处理——(7)简单事件(Simple events)
  • (CPU/GPU)粒子继承贴图颜色发射
  • (Oracle)SQL优化技巧(一):分页查询
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (译)计算距离、方位和更多经纬度之间的点
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .Net 基于IIS部署blazor webassembly或WebApi