Javascript bind函数
什么是bind函数
bind()方法会创建一个新函数,当这个新函数被调用时,bind()的第一个参数将作为它运行时候的this,之后的序列参数将会在传递的实参前传入作为它的参数。
由此可以得出bind函数的两个特点:- 返回一个函数
- 可以传参数
返回函数的模拟实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18Function.prototype.bind1 = function(context){
var self = this
//返回一个函数
return function(){
//这里的self也就是bar,context指的是 obj
return self.apply(context)
}
}
var obj = {
value: 1
}
function bar(){
console.log(this.value)
}
//返回了一个函数
var retFn = bar.bind1(obj)
//执行这个函数 , 相当于 bar.apply(obj)
retFn() // 1传参的模拟实现
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
27Function.prototype.bind1 = function(context){
var self = this
//获取到通过bind1 传递进来的第二个参数,也就是 name
var args = Array.prototype.slice.call(arguments, 1);
return function(){
// 获取到返回函数调用时传递进来的参数 也就是 age
var bindArgs = Array.prototype.slice.call(arguments);
// 将两次获得到的参数 通过 concat函数合并到 bindArgs中
bindArgs = args.concat(bindArgs)
// self 这里指调用bind1的函数 bar,通过apply 将this指向了context也就是 obj,继而访问到value的值,并将参数打印出来
return self.apply(context,bindArgs)
}
}
var obj = {
value: 1
}
function bar(name, age){
console.log(this.value)
console.log(name)
console.log(age)
}
var retFn = bar.bind1(obj, 'blue');
retFn(18);
/* 1
* blue
*/ 18构造函数效果的模拟实现
一个绑定函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器,提供的this值被忽略,同时调用时的参数被提供给模拟函数。
也就是说bind函数返回的函数作为构造函数的时候,bind时指定的this值会失效,但是传入的参数依然生效。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
51Function.prototype.bind1 = function(context){
var self = this
var args = Array.prototype.slice.call(arguments, 1);
var value = 'bind1Value'
var bindFn = function(){
//var value = 'bindFnValue' //this.value 会打印这个值
//小问题:调用 bind 的不是函数咋办?
if(typeof this !== 'function')
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
//优化添加的
var FNOP= function(){}
var bindArgs = Array.prototype.slice.call(arguments)
bindArgs = args.concat(bindArgs);
return self.apply(this instanceof bindFn ? this : context, bindArgs)
}
// 这里可以优化一下
// bindFn.prototype = this.prototype;
// return bindFn;
//优化添加的
FNOP.prototype = this.prototype;
bindFn.prototype = new FNOP();
return bindFn;
}
var value = 2;
var obj = {
value: 1
}
bar.prototype.friend = 'yellow';
function bar(name, age){
this.sex = 'boy'
console.log(this) // bindFn {}
console.log(typeof this) // object
// console.log(this.value) // bindFnValue
// 这里为undefined就是因为this被改变成了bindFn{}
console.log(this.value) // undefined
console.log(name) // blue
console.log(age) // 18
}
// retFn 就是bar,retFn.prototype 就是bar.prototype
var retFn = bar.bind1(obj, 'blue');
var ret = new retFn(18);
console.log(ret.sex); // boy
console.log(ret.friend) // yellow