js手写bind
程序员文章站
2022-06-09 12:58:22
...
js手写bind
首先解释一下bind:
bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。(来自于 MDN )
给个例子:
var value = 'v in window';
function func() {
console.log(this.value);
}
var obj = {
value: 'v in obj'
};
func(); //v in window
var newFunc = func.bind(obj);
newFunc(); //v in obj
用法类似call和apply,调用返回的newFunc函数类似调用func.call(obj)或者func.apply。
根据这个原理,手写一个bind2:
var value = 'v in window';
function func() {
console.log(this.value);
}
var obj = {
value: 'v in obj'
};
Function.prototype.bind2 = function (obj) {
var that = this;
return function () {
that.apply(obj); //call和apply都可以,这里用apply主要是为了方便后面处理带参数的情况
}
};
func(); //v in window
var newFunc = func.bind2(obj);
newFunc(); //v in obj
bind2返回一个函数,调用这个函数时,that指向之前的func,相当于func.apply(obj),实现了bind功能
处理一下带参数的情况:
var value = 'v in window';
function func() {
arguments = [].splice.call(arguments, 0); //这一句是把参数转成数组,因为arguments不是数组,输出的时候容易观察
console.log(arguments);
console.log(this.value);
}
var obj = {
value: 'v in obj'
};
Function.prototype.bind2 = function (obj) {
var that = this;
var args = [].splice.call(arguments,1);
return function () {
that.apply(obj,args);
}
};
func(1,2,3);
//[1,2,3]
//v in window
var newFunc = func.bind2(obj,1,2,3);
newFunc();
//[1,2,3]
//v in window
官方bind还有一个特点:
var value = 'v in window';
function func() {
arguments = [].splice.call(arguments, 0); //这一句是把参数转成数组,因为arguments不是数组,输出的时候容易观察
console.log(arguments);
console.log(this.value);
}
var obj = {
value: 'v in obj'
};
var newFunc = func.bind(obj,1,2,3);
newFunc(4,5,6);
//[1, 2, 3, 4, 5, 6]
//v in obj
如果给newFunc传参数,他可以把参数拼接起来,修改一下
Function.prototype.bind2 = function (obj) {
var that = this;
var args = [].splice.call(arguments,1);
return function () {
var newArgs = [].splice.call(arguments,0); //将newFunc的参数变成数组
that.apply(obj,args.concat(newArgs)); //将上面的数组和之前的参数数组结合
}
};
处理一下返回的函数被作为构造函数的情况:
Function.prototype.bind2 = function (obj) {
var that = this;
var args = [].slice.call(arguments,1);
var func = function () {
that.apply(this instanceof func ? this : obj,args.concat([].splice.call(arguments,0))); //用来判断是不是作为构造函数:this instanceof func === true是则是构造函数
};
fNOP.prototype = this.prototype; //利用空函数fNOP实现继承原型链同时又不改变原函数的原型链
fbound.prototype = new fNOP();
return func;
};
最后处理一下兼容问题:
Function.prototype.bind2 = function (obj) {
if (typeof this !== "function") { //不是函数不能调用bind方法
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var that = this;
var args = [].slice.call(arguments,1);
var func = function () {
that.apply(this instanceof func ? this : obj,args.concat([].splice.call(arguments,0))); //用来判断是不是作为构造函数:this instanceof func === true是则是构造函数
};
fNOP.prototype = this.prototype; //利用空函数fNOP实现继承原型链同时又不改变原函数的原型链
fbound.prototype = new fNOP();
return func;
};
下一篇: AES加解密