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

JS函数的递归和闭包的注意点

时间:2023-03-30 23:10:54 CSS

JavaScript函数表达式——“函数的递归和闭包”的注意点函数表达式的基本概念name属性和函数提升首先是name属性,通过它可以访问给函数的名称。(非标准属性)如:functionPeople(){};console.log(People.name);//人其次,提升了函数声明,就是说函数声明可以放在调用它的语句之后。如:sayHi();//调用函数functionsayHi(){//声明函数console.log("Hi");}//如果使用函数表达式则不会报错:sayHi();varsayHi=function(){console.log("Hi");}//创建报错函数有两种方式,一种是函数声明(如第一种方式);另一种是函数表达式(如第二种方法)。第二种函数创建方式创建的函数称为“匿名函数”或“lambda函数”,因为function关键字后面没有标识符。功能推广常见错误需要注意的是,作为对比,下面两段代码中,第一段是错误的(在不同的浏览器中会出现不同的问题);第二个是正确的。代码如下:varcondition=true;if(condition){functionsayHI(){console.log("hi")}//欢迎加入前端全栈开发交流圈一起学习交流:1007317281sayHI();//"hello"}else{functionsayHI(){console.log("hello")}sayHI();}errorvarcondition=false;varsayHi;if(condition){sayHi=function(){console.log(“你好”)};//欢迎加入前端全栈开发交流圈一起学习交流:1007317281sayHi();}else{sayHi=function(){console.log("hello")};打招呼();//你好}没有错误varcondition=true;如果(条件){varsayHi=function(){console.log("hi")};打招呼();//hi}else{varsayHi=function(){console.log("hello")};打招呼();//hello}这里也没有问题。上述问题的根本原因是函数提升,是函数声明和函数表达式的不同造成的。给大家推荐一个技术交流学习圈,总结了移动应用网站开发,css,html,webpack,vuenodeangular,面试资源。获取资料对web开发技术感兴趣的同学可以加入交流圈???1007317281,不管你是新手还是大牛,都欢迎。还有大牛整理的一套高效学习路线和教程,免费分享给大家。同时每天更新视频数据。函数的递归当函数通过名称调用自身时,就形成了递归函数。如:functionfactorial(num){if(num<=1){return1;}else{返回num*factorial(num-1);.log(阶乘(4));//244*3*2*1但是函数中包含了函数本身,所以应该使用arguments.callee来解决这个问题。例如:functionfactorial(num){if(num<=1){return1;}else{返回num*arguments.callee(num-1);}}console.log(阶乘(4));//244*3*2*1但是如果你用上面的方法,在严格模式下就不行了。但是,您可以使用命名函数表达式来获得相同的结果。例如:varfactorial=(functionf(num){if(num<=1){return1;}else{returnnum*f(num-1);}});console.log(4);factorial//244*3*2*1也就是包含在一个变量中,遇到其他种类的arguments.callee需要用到的时候可以这样做。函数的闭包闭包是一个函数,它可以访问另一个函数范围内的变量。创建闭包的一种常见方法是在另一个函数中创建一个函数。在此之前,你应该先掌握作用域链的概念(见文章《Javascript执行环境和作用域的注意要点》)。作用域链以如下代码为例functioncompare(value1,value2){if(value1>value2){return1;}elseif(value1value2){返回1;}else{返回0;}};}varcompare=createComparisonFunction("name");varresult=compare({name:"Nicholas"},{name:"Greg"});this相当于:varcompare=function(object1,object2){varvalue1=object1["名称"];varvalue2=object2["名称"];如果(值1<值2){返回-1;}elseif(value1>value2){返回1;}else{返回0;}//欢迎加入前端全栈开发交流圈一起学习交流:1007317281};varresult=compare({name:"Nicholas"},{name:"Greg"});等价于:varresult=function(){varvalue1={name:"Nicholas"}["name"];varvalue2={名称:“格雷格”}[“名称"];if(value1value2){return1;}else{return0;}};console.log(result());//1这样,完成代码如下:varcompareNames=createComparisonFunction("name");functioncreateComparisonFunction(propertyName){returnfunction(object1,object2){varvalue1=object1[propertyName];varvalue2=object2[propertyName];value2ifvalue(value1){return-1;}elseif(value1>value2){return1;}else{return0;}//欢迎来到前端全栈开发交流圈学习交流:1007317281name(varcompult=}resname"Nicholas"},{name:"Greg"});compareNames=null;compareNames()函数调用过程中产生的作用域链之间的关系如下:常见的闭包模式一般是这样的this:varX=functionA(a){returnfunction(b1,b2){...a...}//匿名函数};varY=X(b1,b2);例如:varobj1={名称:“co”,颜色:[“白色”,“黑色”]};varobj2={na我:“lor”,颜色:[“黄色”,“红色”]};函数displayProperty(propertyName){returnfunction(obj1,obj2){varvalue1=obj1[propertyName];varvalue2=obj2[属性名];if(typeofvalue1==="string"){returnvalue1+"and"+value2+"
";}elseif(value1instanceofArray){returnvalue1.toString()+"
"+value2.toString();}else{返回错误;}//欢迎加入前端全栈开发交流圈一起学习交流:1007317281};}vardisplayP=displayProperty("name");vardisplayStr=displayP(obj1,obj2);document.write(displayStr);displayP=null;vardisplayP=displayProperty("color");vardisplayStr=displayP(obj1,obj2);document.write(displayStr);/*coandlorwhite,blackyellow,red*/闭包会携带它包含的函数的作用域,所以会占用更多的内存资源。建议仅在绝对必要时才考虑使用闭包。V8优化的js引擎会尝试回收闭包占用的内存。闭包和变量闭包的一个副作用是闭包只获取封闭函数中任何变量的最后一个值。this对象在全局函数this=window;当函数作为对象的方法被调用时,this=thatobject;但是匿名函数的执行环境是全局的,this通常指向window;但也有例外:varname="thewindow";varobj={name:"theobj",getNameFunc:function(){returnfunction(){returnthis.name;};}//欢迎来到前端全栈开发交流圈学习交流:1007317281};console.log(obj.getNameFunc()());//"thewindow"不要忘记写两个括号,因为每个函数在调用时会自动得到两个特殊变量:this和arguments;internal当函数搜索这两个变量时,它只会搜索到它的活动对象。varobj={姓名:“Oliver”,年龄:18,朋友:[“alice”,“troy”],sayName:function(){returnthis.name;},sayFriends:function(){returnfunction(){returnthis.friends;};}};console.log(obj.sayFriends()());//undefined上面的代码是因为闭包的问题,??导致报错。另一个例子:varfriends="window'sfriends";varobj={name:"Oliver",age:18,friends:["alice","troy"],sayName:function(){returnthis.name;},sayFriends:function(){returnfunction(){returnthis.friends;};}//欢迎加入前端全栈开发交流圈一起学习交流:1007317281};console.log(obj.sayFriends()());//window'sfriends匿名函数执行环境全局性解决这个问题的方法是:varfriends="window'sfriends";varobj={name:"Oliver",age:18,friends:["alice","troy"],SayName:Function(){Returnthis.Name;},sayfriends:function(){varginger=this;返回函数(){returnler.friends;};有意识的));//["alice","troy"]这样就可以正常搜索了又如:varfriends="window'sfriends";varobj={name:"Oliver",age:18,friends:["alice"“特洛伊”],sayWindowFriends:function(){returnfunction(){返回this.friends;};},sayFriends:function(){varouter=this;返回函数(){返回函数(){返回函数(){返回外部.friends};};};}};安慰。日志(obj.sayWindowFriends()());//“窗口的朋友”console.log(obj.sayFriends()()()());//["alice","troy"]再举个例子:varobj={name:"Oliver",age:18,friends:["alice","troy"],sayFriends:function(i){varouter=这个;returnfunction(j){返回outer.fr]+outer.friends[j];};}};console.log(obj.sayFriends(0)(1));//alicetroy另外,在几种特殊情况下,this的值可能会改变例如:varname="thewindow";varobj={name:"myobject",getName:function(){returnthis.name;}};console.log(obj.getName());//我的对象控制台.log((obj.getName)());//我的对象和上面一样,只是多了一个括号console.log((obj.getName=obj.getName)());//窗口只需要下面两种方式不需要调用函数。内存泄漏经过上面的一番折腾,最明显的就是window.name一直在占用内存,无法清除。必须手动清理,window.name=null才能操作。感谢大家观看,如有不足,欢迎批评指正。这次给大家推荐一个免费学习群,里面总结了移动应用网站开发,css,html,webpack,vuenodeangular,面试资源。获取信息???欢迎对web开发技术感兴趣的同学加入Q群:???1007317281???,不管你是小白还是大牛我都欢迎,还有大牛整理的一套高效学习路线和教程免费分享给你,视频资料每天更新。最后祝大家早日学业有成,拿到满意的offer,快速升职加薪,走上人生巅峰。