在阅读本文之前,你应该先对call或apply的原理、new操作符、柯里化、原型链机制有一定的了解。1、bind方法的原理当fn(p1,p2,p3)调用bind方法时,fn.bind(obj)会返回一个this指向obj的函数bindFn。bindFn的函数体和fn一样,bind只能接收函数原有的部分参数,让返回的函数处理其他参数,即函数柯里化。2.bind的第一个简单实现因为bind的返回值是一个函数,所以我们需要考虑函数的调用方式。如果函数作为构造函数使用,那么通过new运算符调用它的结果应该和直接调用它的结果是一样的。?在实现bind的过程中,是否需要判断函数的调用方式?对此我百思不得其解,然后先实现了一个不判断调用方法的简单版本://忽略构造函数Function.prototype.myBind=function(thisValue,...firstArgs){//thisValue为返回值function要绑定的thisfirstArgs是第一次传入的参数数组。constcurrentFn=这个;//执行完myBind后,得到的是一个函数体,和调用myBind的函数体是一样的,只不过这个是在返回值函数中绑定的returnfunction(...secondArgs){//secondArgs是参数数组第二次传入returncurrentFn.apply(thisValue,[...firstArgs,...secondArgs])}}functionadd(a,b,c){console.log(this);返回a+b+c}console.log(add(1,2,3));console.log(add.bind(null,1)(2,3));控制台.log(add.bind(obj,1)(2,3));console.log(add.myBind(null,1)(2,3));console.log(add.myBind(obj,1)(2,3));但是如果是构造函数,结果就会不同functionPerson(n,a,s){console.log(这个);this.name=nthis.age=athis.sex=s}Person('小明',18,'男')//this指向窗口constp=newPerson('小华',19,'男')//this指向pconstbindPerson=Person.bind(obj)constmyBindPerson=Person.myBind(obj)constp2=newbindPerson('xiaogou',17,'male')//指向p2constp3=newmyBindPerson('xiaogou',17,'male')//指向obj这是因为虽然new了myBindPerson(),new操作符将myBindPerson内部的this指向了当前实例p3,但是myBindPerson在执行return语句的时候currentFn.apply(thisValue,[])被执行,this被强制绑定到obj,所以this最终输出的是obj。显然,此时我们要判断new操作符调用的函数是否按照new符号的原理进行操作,我们可以使用instanceof的方法来判断。3.bindimplementsFunction.prototype.myBind=function(thisValue,...firstArgs){//thisValue是绑定this的返回值函数firstArgs是第一次传入的参数数组constcurrentFn=this;//创建一个空的中转函数,用于检测是否newconsttempFn=function(){}//如果currentFn是构造函数,且其原型存在,则将中转函数的原型指向当前函数的原型,以维护原型链关系if(currentFn.prototype){tempFn.prototype=currentFn.prototype}//此时tempFn创建的实例作为返回值函数的原型BindFn//new创建的实例的__proto__bindFn()会指向newTemp()//newTempFn()被添加到原型链中,可以通过instanceof来判断是否调用了bindFn。newbindFn.prototype=newtempFn();//以后instanceof可以判断的关键语句functionbindFn(...secondArgs){//调用时如果使用new,即constp=newbindFn()形式,this此时指向p,又因为tempFn的实例是p的原型对象//所以此时pinstanceoftempFn应该为true我们不这样应该改为指向//如果bindFn()是直接调用的,this应该指向window,这时候我们需要绑定thisreturncurrentFn.apply(thisinstanceoftempFn?this:thisValue,[...firstArgs,...secondArgs])}returnbindFn}Person('XiaoMing',18,'Male')//this指向windowconstp=newPerson('小花',19,'男')//这个指向pconstbindPerson=Person.bind(obj)constmyBindPerson=Person.myBind(obj)constp2=newbindPerson('小狗',17,'male')//指向p2constp3=newmyBindPerson('xiaogou',17,'male')//指向p3bindFn4.bind实例的mdn实现我指的是mdn,mdn实现是:if(!Function.prototype.bind){Function.prototype.bind=function(oThis){if(typeofthis!=='function'){thrownewTypeError('绑定对象需要是一个函数')}varself=thisvarargs=[].slice.call(arguments,1)varfunc=function(){}fBound=function(){returnself.apply(thisinstanceoffunc?this:oThis,args.concat([].slice.call(arguments)))}if(this.prototype){func.prototype=this.prototype}fBound.prototype=newfunc()returnfBound}}我使用声明提升机制把varfunc=function(){}if(this.prototype){func.prototype=this.prototype}fBound.prototype=newfunc()放在一起,顺序为方便理解传递函数func的作用,仅供个人理解。如有错误,请指正。如果您觉得对您有帮助,请点个赞吧!
