实现call, apply和bind

实现call, apply和bind

实现call

思想

实现一个call无非就是下面几点:

  1. 第一个参数传入null时,this指向window。
  2. 第一个参数传入对象时,this指向该对象。
  3. 接受剩余参数传入。
  4. 返回函数执行的结果。

代码

1
2
3
4
5
6
7
8
9
10
11
12
Function.prototype.newCall = function(context = window, ...args) {
// 获取this需要指向的对象
const ctx = context || window;
// 保存调用newCall的函数
ctx.fn = this;
// 在新对象上执行函数,传入参数并执行,保存函数的返回值
const res = ctx.fn(...args);
// 考虑到可能绑定到了window,故而删除fn
delete ctx.fn;
// 返回函数的返回值
return res;
};

实现apply

思想

实现一个apply和call类似:

  1. 第一个参数传入null时,this指向window。
  2. 第一个参数传入对象时,this指向该对象。
  3. 接受剩余参数以数组的形式传入。
  4. 返回函数执行的结果。

代码

1
2
3
4
5
6
7
8
9
10
11
12
Function.prototype.newApply = function(context = window, args = []) {
// 获取this需要指向的对象
const ctx = context || window;
// 保存调用newApply的函数
ctx.fn = this;
// 在新对象上执行函数,传入参数并执行,保存函数的返回值
const res = ctx.fn(...args);
// 考虑到可能绑定到了window,故而删除fn
delete ctx.fn;
// 返回函数的返回值
return res;
};

实现bind

思想

bind与call和apply不同,call和apply是执行后返回函数的返回值,而bind返回的是修改后的函数却不执行。

  1. 第一个参数传入null时,this指向window。
  2. 第一个参数传入对象时,this指向该对象。
  3. 接受剩余参数传入。
  4. 返回绑定了新对象的函数。
1
2
3
4
5
6
7
8
9
10
Function.prototype.newBind = function(context, ...args) {
// 获取函数
const _fn = this;
// 返回绑定了新对象的函数
return function Bind(...newArgs) {
// 考虑是否此函数被继承
if (this instanceof Bind) return _fn.newApply(this, [...args, ...newArgs]);
return _fn.newApply(context, [...args, ...newArgs]);
}
}

ref

  1. https://segmentfault.com/a/1190000018832498
  2. https://blog.csdn.net/qq_37288477/article/details/87884518

评论