实现 JS 中的 bind、call、apply 方法

本文探讨了 JavaScript 中 bind、call、apply 三者之间的异同,并详细介绍了如何实现这三个方法。它们均用于改变函数的 this 指向,bind 返回新函数,call 和 apply 直接调用。文章通过类数组对象转数组、普通函数的 this 指向以及 eval 和 new Function() 的使用,展示了不依赖 call 和 apply 实现 bind 的方法。此外,还讲解了如何实现 call 和 apply 功能。
摘要由CSDN通过智能技术生成

bind、call、apply 的异同点

相同点:这三个方法都是 Function.prototype 上的方法,所有的函数实例都可以使用。它们的作用是相同的,都可以改变函数中的 this 指向,实现方法的“j借用”,第一个参数都传入函数新的 this
不同点:bind 和另外两者的不同点是函数调用 bind 方法会返回一个新的函数,而 call 和 apply 被函数调用和函数直接调用类似,返回结果取决于函数原来如何返回。call 和 apply 的不同点在于函数的传参,call 中函数的参数是从第二个开始,依次传入,而 apply 中第二个参数是所有参数组成的参数数组

实现 bind 方法

类似于原始的 bind 方法,要让所有函数实例共用,新的 bind2 也需要将方法挂载到 Function 对象的原型 Function.prototype 上。

实现 bind2 方法要达到的效果是:调用 bind2 方法时,第一个参数是要传入的 this,后边可以传入函数所需的部分或全部参数,最后要 return 一个新函数,新函数中可以继续传入剩余的参数,这个参数和调用 bind2 时传入的参数综合起来,得到一个返回结果,最后在新函数中 return 出来。

因为调用 bind2 时给原来函数传入几个参数是不确定的,所以在 bind2 中可以通过参数对象 arguments 获取到其余参数。如何获取呢?

类数组对象转为数组

因为 arguments 是一个类数组对象,它和数组相似,有类似于下标的属性和 length 属性,类数组对象都可以转化为数组。同时可以注意到,arguments 对象有一个迭代器属性 Symbol(Symbol.iterator),也就是该对象部署了迭代器接口,是可以迭代的。这里的 arguments 对象可以使用 for 循环遍历

将类数组对象转为数组:

// ES2015 之前
// 借用数组原型上的 slice 方法或 for 循环中 arguments[i] 获取每一项
var args = Array.prototype.slice.call(arguments);
var args = [].slice.call(arguments);

// ES2015
// 使用 Array.from 和展开运算符 ... 
const args = Array.from(arguments);
const args = [...arguments];

在 bind2 生成的新函数中也可以这样获取参数,然后在新函数中通过 apply 方法调用函数,改变了函数的 this 指向,也传入了函数所需参数,最后返回结果

function add(a, b) {
   
    return a + b;
}
var fn1 = add.bind(null, 3);
console.log(fn1(4)); // 7



Function.prototype.bind2 = function (context) {
   
    let func = this;
    let previousArgs = [].slice.call(arguments, 1);

	// 闭包
    return function () {
   
        let currentArgs = [].slice.call(arguments);
        let combinedArgs = [].concat(previousArgs, currentArgs); // 所有参数的数组
        return func.apply(context, combinedArgs);
    };
}
var fn2 = add.bind2(null
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值