共计 1870 个字符,预计需要花费 5 分钟才能阅读完成。
之前已经实现过了 call,apply 和 new。今天顺便把 bind 也实现下。首先:
bind 方法返回的是一个绑定 this 后的函数,并且该函数并没有执行,需要手动去调用。(从这一点看 bind 函数就是一个高阶函数,而且和 call,apply 方法有区别)。
bind 方法可以绑定 this,传递参数。注意,这个参数可以分多次传递。
如果 bind 绑定后的函数被 new 了,那么此时 this 指向就发生改变。此时的 this 就是当前函数的实例。
构造函数上的属性和方法,每个实例上都有。
ok,上代码~
Function.prototype.mybind = function(context){
let that = this;
let args1 = Array.prototype.slice.call(arguments,1);
let bindFn = function(){
let args2 = Array.prototype.slice.call(arguments);
return that.apply(this instanceof bindFn?this:context,args1.concat(args2));
}
let Fn = function(){};
Fn.prototype = this.prototype;
bindFn.prototype = new Fn();
return bindFn;
}
首先 获取到第一次传递的参数 args1,此处要做截取处理,因为第一个参数是 this。接下来声明一个函数 bindFn,在该 bindFn 中获取了第二次传的参数 args2,并且返回了 that 的执行。此处的 that 就是原函数,执行该原函数绑定原函数 this 的时候要注意判断。如果 this 是构造函数 bindFn new 出来的实例,那么此处的 this 一定是该实例本身。反之,则是 bind 方法传递的 this(context)。最后再把两次获得的参数通过 concat() 连接起来传递进去,这样就实现了前 3 条。最后一条:构造函数上的属性和方法,每个实例上都有。此处通过一个中间函数 Fn,来连接原型链。Fn 的 prototype 等于 this 的 prototype。Fn 和 this 指向同一个原型对象。bindFn 的 prototype 又等于 Fn 的实例。Fn 的实例的__proto__又指向 Fn 的 prototype。即 bindFn 的 prototype 指向和 this 的 prototype 一样,指向同一个原型对象。至此,就实现了自己的 bind 方法。代码写好了,测试一下吧~
Function.prototype.mybind = function(context){
let that = this;
let args1 = Array.prototype.slice.call(arguments,1);
let bindFn = function(){
let args2 = Array.prototype.slice.call(arguments);
return that.apply(this instanceof bindFn?this:context,args1.concat(args2));
}
let Fn = function(){};
Fn.prototype = this.prototype;
bindFn.prototype = new Fn();
return bindFn;
}
let obj = {
name:’tiger’
}
function fn(name,age){
this.say = ‘ 汪汪~’;
console.log(this);
console.log(this.name+’ 养了一只 ’+name+’,’+age+’ 岁了 ‘);
}
/** 第一次传参 */
let bindFn = fn.mybind(obj,’????’);
/** 第二次传参 */
bindFn(’10’);
/* 构造函数上的属性和方法,每个实例上都有 */
let instance = new bindFn(’20’);
bindFn.prototype.type = ‘ 哺乳类 ’;
console.log(instance.type);
分别在执行 mybind() 和执行 mybind 后函数的时候,传递了两次参数。并且打印了:
tiger 养了一只????,10 岁了
可以看到,实现了分两步传参数。其次,通过 new 得到了构造函数 bindFn 的实例 instance。在构造函数 bindFn 上拓展属性 type 等于 ’ 哺乳类 ’。打印该构造函数的实例 instance,可以看到打印出了:哺乳类。至此,证明了手写的 bind 方法符合所有预期需求。喜欢点个????,thx~