0%

bind的模拟实现

bind的作用

  • bind()方法返回一个新的函数,
  • 新函数的this值指向传入的第一个参数,this被绑定了
  • bind 的时候可以传递参数,进行绑定
  • bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,但传入的参数依然生效

返回函数的模拟实现

1
2
3
4
5
6
Function.prototype.bind = function (context) {
var that = this;
return function () {
return self.apply(context);
}
}

兼容参数处理

bind 的时候可以传递参数,进行绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
Function.prototype.bind = function (context) {
var that = this;
//绑定参数
// 获取bind函数从第二个参数到最后一个参数
var bindArgs = Array.prototype.slice.call(arguments, 1)
return function () {
// 这个时候的arguments是指bind返回的函数传入的参数
var args = Array.prototype.slice.call(arguments)
// 指向函数 返回结果
// 最终执行结果的参数,需要将bindArgs,args使用concat合并
return that.apply(context, bindArgs.concat(args))
}
}

兼容构造函数

bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,但传入的参数依然生效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Function.prototype.bind = function (context) {
var that = this;
// 获取bind函数从第二个参数到最后一个参数
var bindArgs = Array.prototype.slice.call(arguments, 1)
var fBound = function () {
// 这个时候的arguments是指bind返回的函数传入的参数
var args = Array.prototype.slice.call(arguments)
// 指向函数 返回结果
// 最终执行结果的参数,需要将bindArgs,args使用concat合并
// bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,this指向fBound,但传入的参数依然生效
return that.apply(this instanceof fBound ? this : context, bindArgs.concat(args))
}
return fBound;
}

兼容绑定函数原型上的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Function.prototype.bind = function (context) {
var that = this;
// 获取bind函数从第二个参数到最后一个参数
var bindArgs = Array.prototype.slice.call(arguments, 1)
var fNOP = function () { };
var fBound = function () {
// 这个时候的arguments是指bind返回的函数传入的参数
var args = Array.prototype.slice.call(arguments)
// 指向函数 返回结果
// 最终执行结果的参数,需要将bindArgs,args使用concat合并
// bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,this指向fBound,但传入的参数依然生效
return that.apply(this instanceof fBound ? this : context, bindArgs.concat(args))
}
// 修改返回函数的 prototype 为绑定函数的 prototype,实例就可以继承绑定函数的原型中的值
// 直接将 fBound.prototype = this.prototype,我们直接修改 fBound.prototype 的时候,也会直接修改绑定函数的 prototype
// fBound.prototype = this.prototype;

// 通过一个空函数来进行中转
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}

兼容调用 bind 的不是函数

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
Function.prototype.bind = function (context) {
// 调用bind的不是函数,直接报错
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}

var that = this;
// 获取bind函数从第二个参数到最后一个参数
var bindArgs = Array.prototype.slice.call(arguments, 1)
var fNOP = function () { };
var fBound = function () {
// 这个时候的arguments是指bind返回的函数传入的参数
var args = Array.prototype.slice.call(arguments)
// 指向函数 返回结果
// 最终执行结果的参数,需要将bindArgs,args使用concat合并
// bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,this指向fBound,但传入的参数依然生效
return that.apply(this instanceof fBound ? this : context, bindArgs.concat(args))
}
// 修改返回函数的 prototype 为绑定函数的 prototype,实例就可以继承绑定函数的原型中的值
// 直接将 fBound.prototype = this.prototype,我们直接修改 fBound.prototype 的时候,也会直接修改绑定函数的 prototype
// fBound.prototype = this.prototype;

// 通过一个空函数来进行中转
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}

参考

https://github.com/mqyqingfeng/Blog/issues/12

-------------本文结束感谢您的阅读-------------