今天 Joe 老板又给我补课了,他问我call apply bind会用吗,我说会,他又说,把原型函数实现给我写一下,我一下懵逼了,原理,他是来羞辱我的,经过一下午的不懈努力,Joe 老板终于教会了我。
实现call
call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window。
call传参时,是传入1个或多个参数,所以,需要用…展开
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const obj = { name: "我是需要被绑定改变this指向的对象" };
function fn(a, b) { console.log(`This 现在指向 ${this}`); console.log(`传入的 a 是 ${a} ------- b 是 ${b}`); }
Function.prototype.call = function (_this, ...vvhan_com) { const call = Symbol(); _this[call] = this; _this[call](...vvhan_com); delete _this[call]; }; fn.call(obj, 1, 2);
|
实现apply
apply接受两个参数,第一个参数是要绑定给this的值,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。
apply传参时,是传入一个数组,数组里面是参数,所以,不需要用…展开
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const obj = { name: "我是需要被绑定改变this指向的对象" };
function fn(a, b) { console.log(`This 现在指向 ${this}`); console.log(`传入的 a 是 ${a} ------- b 是 ${b}`); }
Function.prototype.apply = function (_this, vvhan_com) { const apply = Symbol(); _this[apply] = this; _this[apply](...vvhan_com); delete _this[apply]; }; fn.apply(obj, [1, 2]);
|
实现bind
和call很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。
bind返回值是函数
因为bind的调用方式,是返回一个新函数,在调用一次,例如:fn.bind(null)(options),所以需要用到高阶函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| const obj = { name: "我是需要被绑定改变this指向的对象" };
function fn(a, b) { console.log(`This 现在指向 ${this}`); console.log(`传入的 a 是 ${a} ------- b 是 ${b}`); }
Function.prototype.bind = function (_this, ...vvhan_com) { const bind = Symbol(); _this[bind] = this; return function (...vvhan_com_) { _this[bind](...(vvhan_com_.length > 0 ? vvhan_com_ : vvhan_com)); delete _this[bind]; }; }; fn.bind(obj, 1, 2);
fn.bind(obj)(1, 2);
|
最后总结
相同点
call、apply、bind的作用都是改变函数运行时this的指向,bind返回对应函数=>便于稍后调用; apply, call则是立即调用。
区别点
apply 和 call 的用法几乎相同, 唯一的差别在于:当函数需要传递多个变量时, apply 传入一个数组作为参数输入, call 则是接受一系列的单独变量。