call、apply、bind是用来改变函数执行时的上下文,简单来说就是改变函数运行时的this点。call传入一个参数列表,apply传入一个数组,但两者都是立即执行的。bind传入参数列表,不会立即执行,适合用在定时器等回调函数中。让fun=dog.eat.bind(cat,'fish');fun();1.从示例代码可以看出,正常情况下,say方法会输出martin。但是我们把say放在了setTimeout方法中,在timer中作为回调函数执行,所以返回主栈执行时,是在全局执行上下文的环境中执行的。此时this指向window,所以lucyconstname为output="lucy";constobj={name:"martin",say:function(){console.log(this.name);}};obj.say();//martin,this指向obj对象setTimeout(obj.say,0);//lucy,this指向window对象其实需要的是this指向obj对象,这时候需要改变this的指向。setTimeout(obj.say.bind(obj),0);//martin,this指向obj对象2,三者的区别可以把函数的this对象改成指向前三个参数是this要指向的对象,如果没有这个参数或者参数未定义或为空,默认指向全局窗口。三者都可以传参,但是apply是一个数组,call是一个参数列表,apply和call是一次性传入的参数,而bind又可以分为多次传bind是绑定this后返回函数,以及apply和call立即执行1)apply方法apply接受两个参数,第一个参数是this的point,第二个参数是函数接受的参数。作为数组传入。原来的函数在改变this的指向后会立即执行,而这个方法只是暂时改变this的指向一次。functionfn(...args){console.log(this,args);}letobj={myname:"张三"}fn.apply(obj,[1,2]);//这将成为passed输入obj必须是一个数组;fn(1,2)//this指向window当第一个参数为null或undefined时,默认指向window(在浏览器中)。fn.apply(null,[1,2]);//这指向windowfn.apply(undefined,[1,2]);//this指向window2)调用方法call方法的第一个参数也是this的指向,后面传入的是一个参数列表。和apply一样,改变this点后会立即执行原函数,这个方法只是临时改变this点一次。functionfn(...args){console.log(this,args);}letobj={myname:"张三"}fn.call(obj,1,2);//this会传入objfn(1,2)//this指向window同样,当第一个参数为null或undefined时,默认指向window(在浏览器中)。fn.call(null,[1,2]);//这指向windowfn.call(undefined,[1,2]);//this指向window3)bind方法bind方法的第一个参数也是this的指向,后面传入的也是一个参数列表(不过这个参数列表可以多次传入)。改变this的point后,不会立即执行,而是返回一个永久改变this的point的函数。functionfn(...args){console.log(this,args);}letobj={myname:"张三"}constbindFn=fn.bind(obj);//this也会传入obj,bind不会立即执行,需要执行一次bindFn(1,2)//this指向objfn(1,2)//this指向window3,基于调用的继承可以通过调用传递,子类可以使用父类方法。功能动物(){这个。eat=function(){log("eating...")}}functionCat(){动物。call(this);}letcat=newCat();cat.吃();4。BindimplementationBindimplementationFunction.prototype.myBind=function(context){//判断调用对象是否为函数if(typeofthis!=="function"){thrownewTypeError("Error");}//获取参数constargs=[...arguments].slice(1);fn=这个;returnfunctionFn(){//根据调用方式,传入不同的绑定值returnfn.apply(thisinstanceofFn?newfn(...arguments):context,args.concat(...arguments));}}
