手写call和apply
# 手写call和apply
call() 方法在使用一个指定的 this 值和”若干个“指定的参数值的前提下调用某个函数或方法。
注意两点:
- call 改变了 this 的指向,指向到 foo
- bar 函数执行了
思路:
- 将函数设为对象的属性
- 执行该函数
- 删除该函数
Function.prototype.myCall = function (context = window, ...args) {
const fnKey = Symbol('fn');
context[fnKey] = this;
const result = context[fnKey](...args);
delete context[fnKey];
return result;
}
Function.prototype.myApply = function (context = window, args = []) {
const fnKey = Symbol['fn'];
context[fnKey] = this;
const result = context[fnKey](...args);
delete context[fnKey];
return result;
}
// es3
Function.prototype.call = function (context) {
// 判断是否存在, context 不为null或者undefined,基本类型主动调用Object(context)
// 不存在赋值 window
context = context ? Object(context) : window;
// 属性 fn 被赋值 this
context.fn = this;
// 收集参数
var args = [];
// 除掉第一个 this, 函数赋值给 fn 外,接收参数
for (var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']');
}
// 创建变量返回结果,eval 执行函数
var result = eval('context.fn(' + args + ')');
// 删除副作用,额外添加的去掉
delete context.fn;
// 返回结果
return result;
}
// es6版本
Function.prototype.call = function (context) {
context = context ? Object(context) : window;
context.fn = this;
let args = [...arguments].slice(1);
let result = context.fn(...args);
delete context.fn;
return result;
}
// es3
Function.prototype.apply = function (context, arr) {
context = context ? Object(context) : window;
context.fn = this;
var result;
// 判断是否存在第二个参数
if (!arr) {
result = context.fn();
} else {
var args = [];
for (var i = 0, len = arr.length; i < len; i++) {
args.push('arr[' + i + ']');
}
result = eval('context.fn(' + args + ')');
}
delete context.fn
return result;
}
// es6
Function.prototype.apply = function (context, arr) {
context = context ? Object(context) : window;
context.fn = this;
let result;
if (!arr) {
result = context.fn();
} else {
result = context.fn(...arr);
}
delete context.fn;
return result;
}
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89