# bind call apply 的实现
# bind
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。bind() 函数会 创建一个新的绑定函数(bound function,BF)。绑定函数是一个 exotic function object(怪异函数对象,ECMAScript 2015 中的术语),它包装了原函数对象。调用绑定 函数通常会导致执行包装函数。 --MDN
bind
函数一般用于手动绑定this
,该函数可以以一种强绑定的方式来绑定 this。也就
是说改变 this 指向后不会立即执行,而是返回一个永久改变 this 值的函数。
实现 bind:
Function.prototype._bind = function (context) {
if (typeof this !== 'function') {
throw new Error(
'Function.prototype.bind - what is trying to be bound is not callable'
)
}
var self = this
// 获取传入参数
var args = Array.prototype.slice.call(arguments, 1)
var fNOP = function () {}
var fBound = function () {
// 此时的argumenty已经是bind返回的函数中传入的参数
var bindArgs = Array.prototype.slice.call(arguments)
// 是否为new调用,该方式调用bind返回函数this会丢失
return self.apply(
this instanceof fNOP ? this : context,
args.concat(bindArgs)
// 函数参数连接起来,柯里化的感觉,延迟执行计算
)
}
// 模拟Object.create
fNOP.prototype = this.prototype
fBound.prototype = new fNOP()
return fBound
}
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
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
# call
call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
call 实现:
Function.prototype._call = function (context) {
// 在非严格模式下,call不指定第一个参数时this绑定到全局对象上
var context = context || window
context.fn = this //获取调用函数
// 获取调用参数 不使用es6
var argus = []
for (var i = 1; i < arguments.length; i++) {
args.push('arguments[' + i + ']')
}
// 执行调用函数
var result = eval('context.fn(' + args + ')')
delete context.fn
return result
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# apply
apply 实现:
Function.prototype.apply = function (context, arr) {
// 严格模式下
var 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
}
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
call 和 apply 的主要作用,是改变对象的执行上下文,并且是立即执行的。它们在参数上 的写法略有区别。
bind 也能改变对象的执行上下文,它与 call 和 apply 不同的是,返回值是一个函数,并 且需要稍后再调用一下,才会执行。