手写call和apply

# 手写call和apply

call() 方法在使用一个指定的 this 值和”若干个“指定的参数值的前提下调用某个函数或方法。

注意两点:

  1. call 改变了 this 的指向,指向到 foo
  2. bar 函数执行了

思路:

  1. 将函数设为对象的属性
  2. 执行该函数
  3. 删除该函数
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
上次更新: 2022/7/6 下午8:56:46