手写call,apply,bind



在日常开发中,bind,call,apply这三个函数是使用率比较高的函数,它们都可以改变函数都执行作用域(改变this),那么我们知道它们是如何实现都吗,下面我们来手动实现以下这三个函数:

call,apply

根据MDN的描述,call 方法调用一个函数, 其具有一个指定的 this 值和分别地提供的参数。call 和 apply 的具体功能相同,唯一的区别是传参方式不一样。call 传参数是分开的,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
25
26
27


//call
Function.prototype.call = function (context) {
let context = context || window;
context.fn = this;
let args = [...arguments].slice(1);
let result = context.fn(...args);
delete context.fn
return result;
}
//apply
Function.prototype.apply = function (context, arr) {
let context = Object(context) || window;
context.fn = this;

let result;
if (!arr) {
result = context.fn();
} else {
let args = [...arr].slice(1);
result = context.fn(...args)
}

delete context.fn
return result;
}

bind

根据MDN描述,bind 方法创建一个新的函数,在调用时设置 this 关键字为提供的值。并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//bind
Function.prototype.bind = function (context) {

if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}

let self = this;
let args = [...arguments].slice(1);

return function F() {
if (this instanceof F) {
return new _self(...args,...arguments);
}
return _self.apply(context,[...args,...arguments]);
}
}