当前位置: 首页 > Web前端 > JavaScript

Bind

时间:2023-03-27 02:15:12 JavaScript

bind()方法创建一个新函数。调用bind()时,将这个新函数的this指定为bind()的第一个参数,其余参数将作为新函数的参数,供调用时使用。constjackdan={age:27,height:185,getAge:function(){returnthis.age;},getHeight:function(){返回this.height;}}constage=jackdan.getAge;console.log(age());//该函数在全局范围内被调用//undefinedconstage1=jackdan.getAge();console.log(age1);//27constjackdanAge=age.bind(jackdan);console.log(jackdanAge());//27语法function.bind(thisArg[,arg1[,arg2[,...]]]);参数说明ThisArg是调用绑定函数时作为this参数传递给目标函数的值。如果使用new运算符构造绑定函数,则忽略此值(为什么?)。当使用bind在setTimeout中创建函数(作为回调提供)时,作为thisArg传递的任何原始值都将转换为对象。如果绑定函数的参数列表为空,或者thisArg为null或未定义,则执行范围的this将被视为新函数的thisArg。为什么new操作符在构造绑定函数时忽略了thisArg?这其实和new算子本身的特性有关。new运算符的特点如下:1.创建一个空的简单JavaScript对象(即{});2.为步骤1新建的对象添加属性`__proto__`,并设置该属性链接到构造函数的原型对象;3.使用第一步新建的对象作为`this`的上下文;4.如果函数没有返回对象,返回`this`。bind的作用:创建一个新的函数(我们可以实际调用它——创建函数的副本),但是将this的值设置为传递给它的第一个参数,也就是thisArgs。new的作用:将this的值设置为新创建的空对象。因此,如果您使用new尝试调用绑定到this关键字值的函数,new关键字将覆盖bind并将this设置为空对象。函数A(){//console.log(this);console.log('test');}vara=newA();//输出测试本机实现:functionA(){console.log('test');}functionNew(fn){varobj={};obj.__proto__=fn.prototype;fn.apply(obj,参数);returnobj;}vara=New(A);//详细输出testnew介绍参考![new]()。arg1,arg2,...调用目标函数时要添加到绑定函数参数列表中的参数。返回值返回具有指定this值和初始参数的原始函数的副本。bind()说明bind()函数创建一个新的绑定函数(BF)。绑定函数是包装原始函数对象的奇异函数对象。调用绑定函数通常会导致执行包装函数。绑定函数具有以下内部属性:1.[[BoundTargetFunction]]-包装函数对象2.[[BoundThis]]-在调用包装函数时始终作为“this”值传递的值。3.[[BoundArguments]]-列表,任何对包装函数的调用都将首先用列表元素填充参数列表。4.[[Call]]-执行与此对象关联的代码。通过函数调用表达式调用。内部方法的参数是一个“this”值和一个包含通过调用表达式传递给函数的参数的列表。调用绑定函数时,它会调用[[BoundTargetFunction]]上的内部方法[[Call]],例如Call(boundThis,args)。其中boundThis是[[BoundThis]],args是[[BoundArguments]]加上通过函数调用传入的参数列表。绑定函数也可以使用new运算符构造,就像目标函数已经构造一样。提供的这个值被忽略,但预参数仍然提供给模拟函数。//希望能仔细运行这个例子,值得反复研究和验证functionmyFunc(){console.log('this=',this.name,'constructor=',this.constructor.name,this.constructor===myFunc)}myFunc.prototype.name="PROTOTYPE";letmyObj={name:'jackdan'};myFunc();//letmyFunc1=newmyFunc();//varbound=myFunc.bind({name:'jackdan'});myObj.f=myFunc;myObj.f();varfunc=newmyFunc();varbound1=myFunc.bind({name:'jackdan'});使用Bind创建绑定函数bind()的最简单使用是创建一个具有相同this值的函数,无论它如何被调用。JavaScript新手常犯的一个错误是从对象中取出一个方法然后调用它,期望方法中的this是原始对象(比如在回调中传入this方法)。如果不做特殊处理,一般会丢失原来的对象。基于这个函数,创建一个与原始对象的绑定函数,巧妙的解决了这个问题://this.age=30;varobj={age:27,getAge:function(){returnthis.X;}}obj.getX();//27vartotalX=obj.getX;总X();//返回30-因为该函数是在全局范围内调用的//创建一个新函数,绑定'this'设置为obj对象//新手可能会将全局变量age与obj的属性age混淆varboundX=totalX.一个函数有默认的初始参数。在此之后将这些参数(如果有的话)写为bind()的参数即可。当调用绑定函数时,这些参数被插入到目标函数参数列表的开头,后面是传递给绑定函数的参数。函数toArray(){returnArray.prototype.slice.call(arguments);}functionaddArguments(arg1,arg2){returnarg1+arg2;}varargList=toArray(1,2,3);//[1,2,3]varresult1=addArguments(1,2);//3//创建一个带有预设参数列表的函数。//创建一个具有默认参数列表的函数。varleadingThirtysevenList=toArray.bind(null,37);//创建一个带有预设第一个参数的函数varaddThirtySeven=addArguments.bind(null,37);varlist2=leadingThirtysevenList();//[37]varlist3=leadingThirtysevenList(1,2,3);//[37,1,2,3]varresult2=addThirtySeven(5);//37+5=42varresult3=addThirtySeven(5,10);//37+5=42,忽略第二个参数配合setTimeout默认情况下,在使用window.setTimeout()时,this关键字会指向window(或global)对象。当一个类方法需要this指向类的一个实例时,你可能需要显式地将this绑定到回调函数上,这样实例的引用才不会丢失。functionLateBloomer(){this.petalCount=Math.ceil(Math.random()*12)+1;}//在1秒后声明开花LateBloomer.prototype.bloom=function(){window.setTimeout(this.declare.bind(this),1000);};LateBloomer.prototype.declare=function(){console.log('我是一朵美丽的花'+this.petalCount+'花瓣!');};varflower=newLateBloomer();开花();//一秒钟后,调用'declare'方法作为构造函数使用的绑定函数绑定函数自动适应使用new运算符构造目标函数创建的新实例。当使用绑定函数构造值时,最初提供的this将被忽略。但是,提供的参数列表仍然会在调用构造函数时插入到参数列表之前(之前也进行了验证)。注意:本部分演示了JavaScript的功能并记录了bind()的高级用法。下面介绍的方法不是最佳解决方案,可能不应该在任何生产环境中使用。函数点(x,y){this.x=x;this.y=y;}Point.prototype.toString=function(){returnthis.x+','+this.y;};varp=newPoint(1,2);p.toString();//'1,2'varemptyObj={};varYAxisPoint=Point.bind(emptyObj,0/*x*/);//下面的polyfill不支持运行这行代码,//但使用原生bind方法就可以了:varYAxisPoint=Point.bind(null,0/*x*/);/*(译注:polyfill的bind方法,如果bind加了第一个参数,即在新的对象上执行Object(this)boundthis,把它包装成一个对象,因为Object(null)是{},所以也可以支持)*/varaxisPoint=newYAxisPoint(5);axisPoint.toString();//'0,5'axisPointinstanceofPoint;//trueaxisPointinstanceofYAxisPoint;//truenewYAxisPoint(17,42)instanceofPoint;//true请注意,如果您不需要做特殊处理,您可以创建一个绑定函数以与new运算符一起使用。也就是说,您无需执行任何特殊操作即可创建可直接调用的绑定函数,即使您更喜欢使用new运算符调用绑定函数。函数点(x,y){this.x=x;this.y=y;}Point.prototype.toString=function(){returnthis.x+','+this.y;};varp=newPoint(1,2);p.toString();//'1,2'varemptyObj={};varYAxisPoint=Point.bind(emptyObj,0/*x*/);//下面的polyfill不支持运行这行代码,//但使用原生bind方法就可以了:varYAxisPoint=Point.bind(null,0/*x*/);/*(译注:polyfill的bind方法,如果bind加了第一个参数,即在新的对象上执行Object(this)boundthis,把它包装成一个对象,因为Object(null)是{},所以也可以支持)*/varaxisPoint=newYAxisPoint(5);axisPoint.toString();//'0,5'axisPointinstanceofPoint;//trueaxisPointinstanceofYAxisPoint;//truenewYAxisPoint(17,42)instanceofPoint;//true//仍然可以作为普通函数调用//(即使通常不会发生这种情况)YAxisPoint(13);emptyObj.x+','+emptyObj.y;//'0,13'如果你想要一个绑定函数或者只使用new运算符,或者只能直接调用,那么你必须在目标函数上显式指定这个限制。当您想要为需要特定this值的函数创建快捷方式时,快捷方式调用bind()也很有用。你可以使用Array.prototype.slice将类数组对象(array-likeobject)转换为真正的数组,仅以它为例。你可以简单地写:varslice=Array.prototype.slice;//...slice.apply(arguments);使用bind()可以简化此过程。下面代码中slice是Function.prototype.apply()方法的绑定函数,Array.prototype的slice()方法作为this的值。这意味着我们根本不需要上面的apply()调用。//与前面代码中的“切片”效果相同varunboundSlice=Array.prototype.slice;varslice=Function.prototype.apply.bind(unboundSlice);//...slice(arguments);绑定实现不支持newFunction.prototype.myBind=function(){varself=this;varthatArgs=arguments[0];varargs=Array.prototype.slice.call(arguments,1);if(typeofself!=='function'){//最接近ECMAScript5的东西//内部IsCallable函数thrownewTypeError('Function.prototype.bind-'+'试图绑定的是不可调用的')}returnfunction(){varfuncArgs=args.concat(Array.prototype.slice.call(arguments));返回self.apply(thatArgs,funcArgs);您可以在脚本的开头插入此代码,从而使您的bind()在没有内置函数的情况下工作。也可以部分地在实现支持它的环境中使用bind。Bind的实现支持newFunction.prototype.myBind=function(context){varself=this;varargs=Array.prototype.slice.call(arguments,1);varfTemp=function(){};varfBound=function(){varbindArgs=Array.prototype.slice.call(arguments);returnself.apply(thisinstanceoffTemp?this:context,args.concat(bindArgs));}fTemp.prototype=this.prototype;fBound.prototype=newfTemp();returnfBound;}varjackdan={age:27,height:185,getAge:function(){returnthis.age;}},getHeight:function(){返回this.height;}}varheight=jackdan.getHeight;varjackdanHeight=height.bind(jackdan);console.log(jackdanHeight());//185Bind示例varobj={firstname:'Dan',lastname:'Jack',age:27,height:185,getName:function(){varfullname=this.firstname+''+this.lastname;返回全名;}};varmyName=function(){console.log(this.getName()+'我选择你!')}varprint=myName.bind(obj);//创建新的对象并绑定对象。obj的'this'===obj现在https://developer.mozilla.org...