前言
bind函数的主要特性:
- 创建一个新的绑定函数,这个函数与被调用的函数具有相同的函数体
- 当这个新函数被调用的时候,函数中this 指向 bind 方法中第一个参数
- 可以传递参数,bind 方法中传递的参数会在绑定函数实参之前
正文
实现bind函数
1、实现绑定指定this与传递参数
'use strict';
Function.prototype.mybind = function(context) {
var _this = this;
var outerArgs = Array.prototype.slice.call(arguments, 1);
return function() {
var innerArgs = Array.prototype.slice.call(arguments);
return _this.apply(context, outerArgs.concat(innerArgs));
}
}
2、当把返回的函数当作构造函数的时候,bind方法中第一个参数会被忽略(即不会绑定this)。
'use strict';
Function.prototype.mybind = function(context) {
var _this = this;
var outerArgs = Array.prototype.slice.call(arguments, 1);
var BoundFn = function() {
var innerArgs = Array.prototype.slice.call(arguments);
// 当此时Fn函数返回出去,被当作构造函数,用new操作符调用的时候,this指向Fn的实例
return _this.apply(this instanceof BoundFn ? this : context, outerArgs.concat(innerArgs));
}
// 把当前函数的prototype赋值给返回函数的prototype
BoundFn.prototype = this.prototype;
return BoundFn;
}
3、上面的代码虽然bind功能实现了,但是存在一个问题,当改变BoundFn函数实例的原型的时候,会影响到原函数的原型,相反也一样,两者的原型是同一个引用,所以需要完善一下。
'use strict';
Function.prototype.mybind = function(context) {
if(typeof this !== 'function') {
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
};
var _this = this;
var outerArgs = Array.prototype.slice.call(arguments, 1);
var BoundFn = function() {
var innerArgs = Array.prototype.slice.call(arguments);
// 当此时BoundFn函数返回出去,被当作构造函数,用new操作符调用的时候,this指向BoundFn的实例
return _this.apply(this instanceof BoundFn ? this : context, outerArgs.concat(innerArgs));
};
var Fn = function() {};
fn.prototype = this.prototype;
BoundFn.prototype = new Fn();
return BoundFn;
}
此时bind函数已经实现了,bind函数在 ECMA-262 第五版才被加入,它可能无法在所有浏览器上运行,所以需要做下兼容:
if(!Function.prototype.bind) {
Function.prototype.bind = function(context) {
if(typeof this !== 'function') {
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
};
var _this = this;
var outerArgs = Array.prototype.slice.call(arguments, 1);
var BoundFn = function() {
var innerArgs = Array.prototype.slice.call(arguments);
// 当此时Fn函数返回出去,被当作构造函数,用new操作符调用的时候,this指向Fn的实例
return _this.apply(this instanceof BoundFn ? this : context, outerArgs.concat(innerArgs));
};
var Fn = function() {};
fn.prototype = this.prototype;
BoundFn.prototype = new Fn();
return BoundFn;
}
}