手写 js 的 call,apply,bind

1
/**
2
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/call
3
 *
4
 * call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
5
 */
6
Function.prototype.Call = function (target, ...org) {
7
  // this 指的是调用的函数 ,这里是下面的Foo函数
8
  target.fn = this
9
  target.fn(...org)
10
}
11
12
/**
13
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
14
 *
15
 * apply() 方法调用一个具有给定this值的函数,以及作为一个数组(或类似数组对象)提供的参数。
16
 */
17
18
Function.prototype.Apply = function (target, org) {
19
  // this 指的是调用的函数 ,这里是下面的Foo函数
20
  target.fn = this
21
  target.fn(...org)
22
}
23
24
/**
25
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
26
 *
27
 * bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
28
 *
29
 * 绑定函数也可以使用 new 运算符构造,它会表现为目标函数已经被构建完毕了似的。提供的 this 值会被忽略,但前置参数仍会提供给模拟函数。
30
 */
31
32
Function.prototype.Bind = function (target, ...org) {
33
  // this 指的是调用的函数 ,这里是下面的Foo函数
34
  const self = this
35
  const Fun = function () {}
36
  function Bound(...newOrg) {
37
    // 普通调用的话,this指的是window 。 作为构造函数调用的话,this指的是构造函数Foo的实例 Foo {}
38
    return self.apply(this instanceof self ? this : target, [...org, ...newOrg])
39
  }
40
  Fun.prototype = this.prototype
41
  Bound.prototype = new Fun()
42
  return Bound
43
}
44
45
const obj = { name: 'xm' }
46
const params = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
47
48
function Foo(...args) {
49
  this.name = args[0]
50
  console.log(args)
51
}
52
53
Foo.Call(obj, ...params)
54
//  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
55
56
Foo.Apply(obj, params)
57
//  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
58
59
const func = Foo.Bind(obj, ...params)
60
const f = func(5000)
61
// [(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 5000)]
62
63
const n = new func(5000)
64
// Foo { name: 1 }