视频教程-call&&apply上次Review调用,apply和bind均来自Function.prototype,旨在改变函数这个点在身体。例如//有一只猫叫小黑,会吃鱼constcat={name:'小黑',eatFish(...args){console.log('this指向=>',this);console.log('...args',args);console.log(this.name+'吃鱼');},}//有一只狗叫大毛,可以吃骨头constdog={name:'大毛',eatBone(...args){console.log('this指向=>',this);console.log('...args',args);console.log(this.name+'吃骨头');},}console.log('====================调用==========================');//有一天大毛想吃鱼,但是不知道怎么吃。该怎么办?小黑说要喂你cat.eatFish.call(dog,'woofwoof','call')//大毛决定下次再喂小黑dog.eatBone吃骨头表示感谢。call(cat,'喵喵喵','call')console.log('=====================apply===========================');cat.eatFish.apply(dog,['Wow','apply'])dog.eatBone.apply(cat,['喵喵喵','申请'])console.log('====================bind===========================');//有一天他们觉得每次吃饭都要喂他们太麻烦了。简单教对方怎么吃consttest1=cat.eatFish.bind(dog,'Wow','bind')consttest2=dog.eatBone.bind(cat,'喵喵喵','bind')test1()test2()方法分解了Apply()的使用:apply()方法使用给定的this值调用一个函数,并将参数作为数组(或类数组对象)提供。func.apply(thisArg,[argsArray])ThisArg可选参数。func函数运行时使用的this值。注意函数执行时不一定是this的真实值:如果函数是非严格模式,当指定为null或undefined时,会自动指向全局对象(window对象中的browser),当值为原值(1,'string',true)时,这将指向原值的自动换行对象(Number,String,Boole)。argsArray可选参数。数组或类数组对象(NodeList),数组元素的每一项都将作为单独的参数传递给func函数。如果这个参数的值为null或undefined,则表示不需要传入任何参数。从ECMAScript5开始可以使用类数组对象。妙用一:数组拼接vararray=['a','b'];变量元素=[0,1,2];array.push.apply(数组,元素);控制台信息(数组);//["a","b",0,1,2]解决想修改原数组的问题,不用循环,想传一个数组妙用2:求最大值array/*找出数组中最大/最小的数*/varnumbers=[5,6,2,3,7];/*Apply(应用)Math.min/Math.max内置函数完成*/varmax=Math.max.apply(null,numbers);/*基本上等同于Math.max(numbers[0],...)或Math.max(5,6,..)*/varmin=Math.min.apply(null,numbers);console.log(max,min)如果已知数组中全是数字,而我们想知道最大的数,由于Array没有max方法,我们可以将这个数组作为参数传递给Math对象上的最终Math,根据应用参数的特点。调用max函数时,apply数组中的参数会一个一个传入,正好符合Math.max的传参方式,变相实现了数组的max方法。min方法还有Argumentlengthlimitedto65536的限制。妙用三:伪数组转换vararrayLike={0:'xiaobai',1:'xiaohei',2:'xiaohong',length:3}vararr=阵列。prototype.slice.call(arrayLike);console.log(arr)魔法四:变量类型判断函数isArray(obj){returnObject.prototype.toString.call(obj)=='[objectArray]';}console.log(isArray([]))console.log(isArray('qianduan'))toString()方法允许修改。上面假设它没有被修改。toString()是Object的原型方法,Array、function等类型作为Object的实例重写了toString方法。不同对象类型调用toString方法时,调用对应重写的toString方法(函数类型返回内容为函数体的字符串,Array类型返回由元素组成的字符串),而不是调用Object上的原型toString方法(返回对象的具体类型),所以obj.toString()无法获取到它的对象类型,只能将obj转换成字符串类型;因此,当你想获得对象的具体类型时,你应该调用对象原型的toString方法。妙用五:构造继承函数Animal(name,age){this.name=name;this.age=age;}functionDog(){Animal.apply(this,['cat','5']);//动物。调用(这个,'猫','5');这。说=功能(){控制台。log(this.name+":"+this.age);}}vardog=newDog();狗说();//cat:5new的Dog中的this指向创建的狗对象,然后执行构造函数中的代码,执行keyapply,将当前环境的this(狗对象)赋值给Animal,所以Animal中的this指向狗对象。在Animal中定义了name和age属性,相当于在dog中定义了这些属性,所以dog对象具有在Animal中定义的属性,从而实现继承目的call()用法:call()方法调用一个带有a的函数指定此值并单独提供参数(参数列表)。apply的语法糖。fun.call(thisArg,arg1,arg2,...)thisArg可选参数。func函数运行时使用的this值。注意函数执行时不一定是this的真实值:如果函数是非严格模式,当指定为null或undefined时,会自动指向全局对象(window对象中的browser),当值为原值(1,'string',true)时,这将指向原值的自动换行对象(Number,String,Boole)。argsArray可选参数。指定的参数列表。误区一:调用匿名函数误区一:调用匿名函数兼容严格模式。在严格模式下,匿名函数中的this会报错。它还实现了匿名函数,对不同的this做不同的处理。奇迹二:字符串分离与连接vartemp=Array.prototype.join.call('hellow!',',');console.log(temp)没有字符串的join方法,所以借用Array奇迹3:StringstakeeachItemArray.prototype.map.call('foo',(item)=>{console.log(item)})。加入('');String没有join方法,从ArrayBind()借用:bind()方法创建一个新函数,在调用时将this关键字设置为提供的值。并且在调用新函数时,将给定的参数列表作为原函数参数序列的前几项。function.bind(thisArg[,arg1[,arg2[,...]]])thisArg调用绑定函数时作为this参数传递给目标函数的值。如果绑定函数是使用new运算符构造的,则忽略此值。当使用bind在setTimeout(作为回调提供)中创建函数时,作为thisArg传递的任何原始值都将转换为对象。如果绑定函数的参数列表为空,则执行范围的this将被视为新函数的thisArg。argsArray在调用目标函数时添加到绑定函数参数列表的参数。说明:ES6的new方法,这个方法会返回一个新函数(函数调用的方法),调用新函数,原函数的方法会作为传入对象的方法,new的任何参数function会被传入也会被传给原来的函数。基本功能f(x){console.log(this.a+x);//原函数}varobj={a:1//传入对象}varnewFn=f.bind(obj)//原函数的方法作为传入对象的方法使用newFn(2)//调用新函数setTimeout(function(){console.log(this.name+":Gotit!")}.bind(this),30)daily(){this.enjoy(function(){this.eat()this.drink()this.sleep()}.bind(this))}如果使用new操作符构造生成的绑定函数,则忽略绑定设置this。返回函数用作构造函数f(x){this.a=1;this.b=function(){returnthis.a+x}}varobj={a:10}varnewObj=new(f.bind(obj,2))//引入一个实参2console.log(newObj.a)//输出1,表示当返回函数作为构造函数时,忽略obj(this的值)console.log(newObj.b())//输出3,表示实参2传入的是传入原函数original不传值window.color='red';functionsayColor(){console.log(this.color);}varfunc2=sayColor.bind();//这个是一样的//输出“red”,因为传了'',this代表全局范围的window.相当于过窗了。func2();多次绑定会发生什么?在Javascript中,多个bind()是无效的。更深层次的原因是,bind()的实现相当于用函数在里面包裹了一个call/apply,第二次bind()相当于又把第一次bind()包裹了一遍,所以第二次之后的bind是无法生效。多重绑定函数say(){console.log(this.x);};vara=say.bind({x:1});varb=a.bind({x:2});b()vara=function(){returnsay.apply({x:1});//改变这个说};varb=function(){returna.apply({x:2});//改变a的这个};妙用一:偏函数(让一个函数有预设初始参数)//在绑定this的同事中输入几个值作为默认参数,执行后传入的参数默认排在参数之后。constobj={}functionf(...args){console.log(args)}constnewFn=f.bind(obj,'1','2')newFn('3','4')函数添加(arg1,arg2){returnarg1+arg2}//创建一个带有预设第一个参数的函数varaddThirtySeven=add.bind(null,37);varresult3=addThirtySeven(5,10);安慰。log(result3)//37+5=42,忽略第二个参数妙用二:快速调用
