0%

手写实现 call、apply、bind

call

  • 获取第一个参数,若不存在则为 window
  • 执行 & 删除这个函数
  • 指定 this 到函数并传入给定参数执行函数
  • 如果不传入参数,默认指向为 window
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
Function.prototype.myCall = function (context, ...args) {
// 若第一个参数传入 null 或 undefined,this 指向 window
if (context === undefined || context === null) {
context = window;
}
// 在 context 上加一个唯一值,避免影响 context 上的属性
const key = Symbol('key');
// 此处的 this 指的是传入的函数
context[key] = this;
// 调用函数
const result = context[key](...args);
// 删除副作用,避免 context 的属性越来越多
delete context[key];

return result;
}

function f(a, b) {
console.log(a, b)
console.log(this.name)
}
let obj = {
name: '张三'
}
f.myCall(obj, [1, 2]);

apply

apply 与 call 几乎完全一样,只是传入的参数形式不同

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
Function.prototype.myApply = function (context, args) {
// 若第一个参数传入 null 或 undefined,this 指向 window
if (context === undefined || context === null) {
context = window;
}
// 在context上加一个唯一值,避免影响 context 上的属性
const key = Symbol('key');
// 此处的 this 指的是传入的函数
context[key] = this;
// 调用函数
const result = context[key](...args);
// 删除副作用,避免 context 的属性越来越多
delete context[key];

return result;
}

function f(a, b) {
console.log(a, b)
console.log(this.name)
}
let obj = {
name: '张三'
}
f.myApply(obj, [1, 2]);

bind

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
Function.prototype.myBind = function (context, ...args) {
if (typeof (this) !== 'function') {
throw new TypeError('The bound object needs to be a function');
}
const _this = this;

return function newFunction() {
// 使用了 new
if (this instanceof newFunction) {
return new _this(...args);
} else {
return _this.call(context, ...args);
}
}
}

let a = {
name: 'poetries',
age: 12
}
function foo(a, b) {
console.log(this.name);
console.log(this.age);
console.log(a);
console.log(b);
}
foo.myBind(a, 1, 2)(); // => 'poetries'

本文标题:手写实现 call、apply、bind

文章作者:Flower-F

发布时间:2022年01月10日 - 23:28

最后更新:2022年01月19日 - 16:40

-------------本文结束,感谢您的阅读-------------

欢迎关注我的其它发布渠道