【模拟实现】Call/Apply/Bind
williamzhou 3/24/2021 面试模拟实现
# 原理
三个方法经常用来改变this
的指向。
其中 call
、apply
是立即执行的,bind
返回一个函数下次调用。
- this (opens new window)
- Function.prototype.call() (opens new window)
- Function.prototype.apply() (opens new window)
- Function.prototype.bind() (opens new window)
# 使用场景
call
、apply
的使用场景
- 对象继承
- 借用方法
# 代码实现
/**
* 模拟实现 call
* this 指向要调用的函数
* @param {*} context 传入的对象
* @param {...any} args 参数
*/
Function.prototype.myCall = function(context, ...args) {
const obj = context ? new Object(context) : window
const key = Symbol()
obj[key] = this
const result = obj[key](...args)
delete obj[key]
return result
}
/**
* 模拟实现 apply
* this 指向要调用的函数
* @param {Object} context 传入的对象
*/
Function.prototype.myApply = function(context) {
const obj = context ? new Object(context) : window
const args = arguments[1]
const key = Symbol()
obj[key] = this
const result = args ? obj[key](...args) : obj[key]()
delete obj[key]
return result
}
/**
* 模拟实现 bind
* this 指向要调用的函数
* @param {Object} context 传入的对象
* @param {...any} args
*/
Function.prototype.myBind = function(context, ...args) {
const fn = this
const bindFn = function (...newFnArgs) {
return fn.call(
this instanceof bindFn ? this : context,
...args,
...newFnArgs
)
}
bindFn.prototype = Object.create(fn.prototype)
return bindFn
}
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
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
# 测试一下
window.name = 'Rocky'
const person1 = {
name: 'Tom',
say(arg1, arg2) {
console.log(`my name is ${this.name}, ${arg1}-${arg2}`)
}
}
const person2 = {
name: 'Jerry'
}
person1.say('aaa', 'bbb') // Tom
person1.say.call(person2, 'ccc', 'ddd') // Jerry
person1.say.myCall(null, 'ddd', 'eee') // Rocky
person1.say.myApply(person2, ['fff', 'ggg']) // Jerry
person1.say.myApply(null, ['hhh', 'iii']) // Rocky
var newSay = person1.say.bind(person2, 'jjj')
newSay('kkk', 'lll') // Jerry jjj-kkk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18