JS手写apply,call,bind函数

本篇文章咱们来手写简易版的apply,call,bind函数。

实现思路

首先咱们需要思考下这三个函数放到哪里比较合适,因为这三个函数是被函数对象调用的,并且每个函数都可以调用,所以不难想到有一个位置非常合适,函数的显式原型对象上,这样就可以通过原型链被每个函数调用。

手写apply

apply函数可以传入两个参数,第一个参数是需要绑定的this对象,第二个参数是传递给函数的参数组成的数组,咱们可以从apply函数的用法倒推它的代码实现。

首先声明一个foo函数,作为测试函数,代码如下图:

之后在函数的显式原型对象上声明一个myapply函数,代码如下图:

第一个参数是执行apply函数后调用函数的对象,为了确保传入的内容是个对象,咱们需要对传入的第一个参数进行判断和处理,代码如下图:

之后咱们需要修改this指向,myapply本身也是个函数,调用者就是使用myapply的函数对象,也就是说此时的this就是调用myapply的函数对象,咱们就可以借助this来建立newObj与调用myapply的函数对象之间的调用关系,代码如下图:

上图可见,在newObj上添加一个fn属性值为调用myapply函数的函数对象,然后执行fn,调用fn后删除newObj上多余的fn属性。

第二个参数是参数构成的数组,可以通过解构的方式获取这些参数,代码如下图:

这样咱们就实现了自己的apply函数。

手写call

call和apply第一个参数接收的内容一致,call的后续参数通过参数列表的方式传入,实现思路与apply一样,只是接收参数的方式不同,区别如下图:

其他的代码与myapply函数一样。

手写bind

bind的函数的第一个参数接收的内容与apply和call一致,后续参数也是通过参数列表的方式传入,不过bind的内部实现不同之处在于,bind返回了一个具有所需this指向的新函数,代码如下图:

其他的代码与mycall函数一样。

完整代码

javascript 复制代码
function foo(name, age) {
    console.log(this, name, age);
}

Function.prototype.myapply = function(newObj, args) {
    newObj = (newObj === null || newObj === undefined) ? window : Object(newObj);

    newObj.fn = this;
    newObj.fn(...args);

    delete newObj.fn;
}

Function.prototype.mycall = function(newObj, ...args) {
    newObj = (newObj === null || newObj === undefined) || Object(newObj);

    newObj.fn = this;
    newObj.fn(...args);

    delete newObj.fn;
}

Function.prototype.mybind = function(newObj, ...args) {
    newObj = (newObj === null || newObj === undefined) ? window : newObj;
    newObj.fn = this;

    return () => {
        newObj.fn(...args);
    }
}

foo.myapply({ name:"guanju"}, ["test", 18])
foo.mycall({ name:"guanju"}, "test", 18);
const foo1 = foo.mybind({ name:"guanju"}, "test", 18);
foo1()
相关推荐
不爱说话郭德纲4 分钟前
我只给了 TRAE Work 一张差评截图,它最后却把自己的 P0 结论推翻了?
前端·后端·架构
猿长大人6 分钟前
C# | 函数式编程入门
开发语言·c#·.net
W_3260010 分钟前
Python 组合数据类型——序列(列表 & 元组)
开发语言·python
Billy1213815 分钟前
Day10-C++20 Ranges(上):惰性求值与组合式数据处理
开发语言·c++进阶学习
张元清17 分钟前
React useEvent Hook:告别过期闭包的稳定回调 (2026)
javascript·react.js
用户9385156350717 分钟前
从 DOM 编程到声明式 UI:React useRef 与 useState 底层全解析
前端·javascript·react.js
小月土星20 分钟前
19.LeetCode 删除链表的倒数第 N 个节点 超详细题解(JS 版)
javascript
kisshyshy29 分钟前
前端路由进化史:从刷新白屏到SPA,手写一个Hash路由就懂了!
前端·javascript·react.js
有点。29 分钟前
C++深度优先搜索(二)
开发语言·c++·深度优先
二进制杯莫停37 分钟前
A和B环境的python版本相同,B环境无法安装pip依赖,离线安装
开发语言·python·pip