# 实现 call
Function.prototype.myCall = function(context, ...args) {
//判断边界条件
if (typeof this !== 'function')
throw new Error('caller must be a function!调用对象不是函数')
context = context || globalThis
//传入context为基本类型时,将其转为对应的引用类型
if (typeof context !== 'object') context = new context.constructor(context)
// 将函数(this)挂在待绑定的this上下文下面,然后调用
const key = Symbol('key') //设置唯一值
context[key] = this
//调用函数
const result = context[key](...args)
delete context[key]
return result
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
另一种写法:
Function.prototype.call = function(context) {
if (typeof this !== 'function') {
throw new Error(
'Function.prototype.bind - what is trying to be bound is not callable'
)
}
/* Array.prototype.slice.call(arguments) */
/* let L = arguments.length,
args = []
for (let i = 1; i < L; i++) {
args.push(arguments[i])
} */
args = [...arguments]
let key = Symbol('key')
context[key] = this
eval('context[key](' + args + ')')
delete context[key]
}
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
# 实现 apply
apply 和 call 类似,只是参数类型不同,apply 的参数是数组,call 的参数是一个个的值
Function.prototype.myApply = function(context, args = []) {
//判断边界条件
if (typeof this !== 'function')
throw new Error('caller must be a function!调用对象不是函数')
context = context || globalThis
//传入context为基本类型时,将其转为对应的引用类型
if (typeof context !== 'object') context = new context.constructor(context)
if (!Array.isArray(args)) {
throw new TypeError('CreateListFromArrayLike called on non-object')
}
// 将函数(this)挂在待绑定的this上下文下面,然后调用
context.fn = this
//调用函数
const result = context.fn(...args)
delete context.fn
return result
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
另一种写法:
Function.prototype.apply = function(context) {
let args = arguments[1]
let fn = Symbol('fn')
context[fn] = this
eval('context[fn](' + args + ')')
delete context[fn]
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 实现 bind
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用
Function.prototype.myBind = function(context, ...args) {
if (typeof this !== 'function') {
throw new TypeError('caller must be a function!')
}
context = context || globalThis
if (typeof context !== 'object') context = new context.constructor(context)
//待绑定的函数
let toBindFunc = this
// 返回一个函数
return function boundFunction() {
// 因为返回了一个函数,可能会通过new调用
if (this instanceof boundFunction) {
//传入的参数覆盖默认参数
return new toBindFunc(...args, ...arguments)
}
//传入的参数覆盖默认参数
return toBindFunc.apply(context, args.concat(...arguments))
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19