-
Notifications
You must be signed in to change notification settings - Fork 0
/
MyCallApplyNewBind.js
99 lines (92 loc) · 2.99 KB
/
MyCallApplyNewBind.js
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
90
91
92
93
94
95
96
97
98
99
/*
实现 Call
1. 判断当前this是否为函数,防止Function.prototype.myCall() 直接调用
2. context 为可选参数,如果不传的话默认上下文为 window
3. 为context 创建一个 Symbol(保证不会重名)属性,将值设置为需要调用的函数
4. 处理参数,传入第一个参数后的其余参数
5. 调用函数后即删除该Symbol属性
*/
Function.prototype.myCall = function(context = window, ...args) {
if (this != Function.prototype) {
return undefined;
}
context = context || window;
const fn = Symbol();
context[fn] = this;
const result = context[fn](...args);
delete context[fn];
return result;
};
/*
实现 apply
和 call 类似,不过参数是数组
*/
Function.prototype.myApply = function(context = window, args) {
if (this != Function.prototype) {
return undefined;
}
context = context || window;
const fn = Symbol();
context[fn] = this;
let result;
if (Array.isArray(args)) {
result = context[fn](...args);
} else {
result = context[fn]();
}
delete context[fn];
return result;
};
/*
new 实现:
var arr = new Array();
在调用 new 的过程中会发生以上四件事情:
1. var obj = {}; 新生成了一个对象
2. obj.__proto__ = Array.prototype; 链接到原型
3. Array.call(obj); 绑定 this
4. 返回新对象
*/
function myNew() {
let obj = {};
let Constructor = [].shift.call(arguments); // 把第一个参数(构造函数名)弹出
obj._proto_ = Constructor.prototype; // 链接原型
let result = Constructor.apply(obj, arguments); // 执行构造函数(此时 arguments 里面只有剩余的参数了),并将 this 指向空的 obj 对象
return result instanceof Object ? result : obj; // 如果是一个对象,就返回这个对象,如果没有,该返回什么就返回什么。
// return obj;
}
/*
Bind 作用:
1、函数调用,改变this
2、返回一个绑定 this 的新函数
3、接收多个参数
4、支持柯里化形式传参 fn(1)(2)
实现 Bind:
1.处理参数,返回一个闭包
2.判断是否为构造函数调用,如果是则使用 new 调用当前函数
3.如果不是,使用apply,将context和处理好的参数传入
*/
Function.prototype.myBind = function(context, ...args1) {
if (this === Function.prototype) {
throw new TypeError("Error");
}
const _this = this;
return function F(...args2) {
// 判断是否用于构造函数
if (this instanceof F) {
return new _this(...args1, ...args2);
}
return _this.apply(context, args1.concat(args2));
};
};
const XY = {
x: 42,
getX: function() {
return this.x;
}
};
const unboundGetX = XY.getX;
// expected output: undefined
console.log(unboundGetX()); // The function gets invoked at the global scope
const boundGetX = unboundGetX.myBind(XY);
// expected output: 42
console.log(boundGetX());