当前位置: 首页 > 后端技术 > Node.js

nodejs中call和apply的学习

时间:2023-04-03 12:20:03 Node.js

接触了很多nodejs的知识点,但是自己没有做过自组织和归纳,等再用的时候还是不清楚。这是一种病,可以治愈。在此希望通过记录加深理解。1.简介:scope和context总的来说:scope与调用函数访问变量的能力有关,context与this关键字有关,是对当前可执行代码的引用。1.1作用域作用域分为局部作用域和全局作用域,作用域往往与变量有关系。局部作用域可以访问全局作用域内的变量,局部作用域外不能访问局部作用域内的变量。看代码:varglobalVariable='thisisglobalvariable';functionglobalFunction(){varlocalVariable='thisislocalvariable';控制台日志(全局变量);//这是全局变量console.log(localVariable);//这是局部变量globalVariable='globalVariablehaschanged';functioninnerFunction(){varinnerLocalVariable='这是内部局部变量';控制台日志(全局变量);//globalVariable改变了console.log(localVariable);//这是局部变量console.log(innerLocalVariable);//这是内部局部变量}innerFunction();}globalFunction();1.2ContextContext往往表示这个变量的值及其方向,它决定了一个函数如何被调用,当一个函数作为对象的方法被调用时,this总是指调用该方法的对象。varpet={words:'...',speak:function(){console.log(this.words);//'...'console.log(this===pet);//真}}pet.speak();'==='表示不仅值相等,而且类型相同,this指向调用speak方法的pet对象,对比如下代码:functionpet(words){this.words=words;控制台日志(单词);//'...'console.log(this===pet)//falseconsole.log(this===global)//true}pet('...');这里this指向运行环境的顶级全局对象,可以直接使用console.log(this)查看。继续看一段代码:functionPet(words){this.words=words;this.speak=function(){console.log(this.words);//miaoconsole.log(this);//打印出当前对象{words:'miao',speak:[Function]}}}varcat=newPet('miao');cat.speak();*注:引入箭头函数=>后,this指向的不是函数调用的对象,而是它的父对象varwords='global';varpet={words:'...',speak:()=>{console.log(this.words);//'全局'console.log(this===pet);//假}}pet.speak();//pet的父对象Window2.call和apply可以通过使用call和apply改变上下文执行对象,在自定义的上下文中执行函数,两者的功能是一样的,只是方法的第二个参数不同,call直接使用参数列表,apply使用参数数组。具体作用是调用一个对象的方法,将当前对象替换为另一个对象,真正改变this指向的对象的内容。看代码:varpet={words:'...',speak:function(say){console.log(say+''+this.words);}}pet.speak('Speck');//Speck...没问题!,修改代码,再看一遍:varpet={words:'...',speak:function(say){console.log(say+''+this.words);}}vardog={words:'wang'}pet.speak.call(dog,'Speak');//Speakwangdog对象本来就没有speak方法。通过call方法,将原来指向pet的this变量改为指向dog。因此,在运行时,这个.words='wang',所以打印出Speakwang。这样,我们就可以让一个对象使用另一个对象的方法。一个很容易想到的应用场景就是继承。函数宠物(单词){this.words=words;this.speak=function(){console.log(this.words);}}functionDog(words){//Pet.call(this,words);//Pet中的this指向当前的Dog,这样Dog就有了Pet的方法Pet.apply(this,[words]);//apply的第二个参数是一个数组}vardog=newDog('wang');dog.speak();我们可以看到使用call和apply的效果是一样的,只是参数的不同,一个直接使用words,一个以数组的形式使用[words]。再看一个例子:functionprint(a,b,c,d){alert(a+b+c+d);}functionexample(a,b,c,d){//通过调用借用print和参数显式分解并传递print.call(this,a,b,c,d);//使用apply借用print,参数以数组形式传递,//可以直接在JavaScript方法本身使用arguments数组print.apply(this,arguments);//或者封装成一个数组print.apply(this,[a,b,c,d]);}至于什么时候用call,什么时候用apply,一般在参数比较清楚的情况下,两者Either即可用过的。当参数不清楚时,推荐使用apply+arguments方式。3.结语本文主要参考了慕课网,攻克nodejs的基础(一)中的http源码解读,以及javascript中apply()和call()方法的区别的博客文章,加上自己的理解.,如有错误,欢迎指出。