前言
bind 的实现其实非常考验对原型链的理解。
bind 和 apply,call 是 JS 修改 this 指向的三把利器 🔱。
对于 apply,call 来说,bind 的区别在于会返回一个修改了 this 指向的新函数,并不会立即执行。
但看似简单的内容,实则包含了 JS 的两大核心内容:原型链和构造函数 (new) 。
这篇文章分为两部分:
- 一部分讲如何实现一个基础版本的 bind 方法,带大家做好热身运动;
- 另一部分进入主题,详细讲解如何通过原型链来实现一个让人眼前一亮的 bind 方法 ✨。
一、实现 bind 方法
简单说,bind 方法会返回一个改变了 this 指向的新方法。
举个 🌰:
var name = 'Jack';
var Yve = {
name: 'Yvette'
};
function person() {
console.log(this.name);
}
person(); // Jack
var bindYve = person.bind(Yve);
bindYve(); // Yvette
根据这个特点,我们来实现第一版的 bind 方法:
// v1.0:返回一个改变了 this 指向的方法
Function.prototype.bind2 = function (context) {
// 首先要获取调用bind的函数,也就是绑定函数,用this可以获取
var self = this; // 用self绑定this,因为下面函数中的this指向已经改变(存放当前函数的this)
return function () {
// 用apply来改变this指向(apply的实现并不复杂,文末放有链接可以查看)
self.apply(context);
}
}
bind 方法的另一个特点是:函数的参数可以分多次传入,即可以在 bind 中传入一部分参数,在执行返回的函数的时候,再传入另一部分参数。
举个 🌰:
var name = 'Jack';
var Yve = {
name: 'Yvette'
};
function person(age, job, gender) {
console.log(this.name, age, job, gender);
}
person(22, 'engineer', 'female');
// Jack 22 engineer female
var bindYve = person.bind(Yve, 22, 'engineer');
bindYve('female');
// Yvette 22 engineer female
根据这个特点,我们来实现第二版的 bind 方法:
// v2.0:分段接收参数
Function.prototype.bind2 = function (context) {
// 首先要获取调用bind的函数,也就是绑定函数,用this可以获取
var self = this; // 用self绑定this,因为下面函数中的this指向已经改变(存放当前函数的this)
var args = [...arguments].slice(1); // 用slice方法取第二个到最后一个参数(获取除了this指向对象以外的参数)
return