当前位置: 首页 > 科技观察

Web前端:征服JavaScript面试什么是闭包?

时间:2023-03-13 12:06:15 科技观察

前言闭包通常是我在一系列面试问题中提出的第一个或最后一个问题。坦率地说,如果您不能理解闭包,那么您就不会在JavaScript中走得太远。别看,就是你。你真的了解如何构建一个严肃的JavaScript应用程序吗?您真的了解幕后发生的事情或应用程序的工作原理吗?我对此表示怀疑。如果你连一个闭包问题都想不通,那就有点尴尬了。你不仅要了解闭包的机制,还要了解为什么闭包很重要,你可以轻松回答闭包的几种可能应用场景。闭包常用于JavaScript中以保持对象数据的私有性,常用于事件处理和回调函数,以及部分应用程序、柯里化和其他函数式编程模型。我不在乎面试官是否知道“关闭”这个词或它的专业定义。我只是想知道他们是否了解基本原理。如果他们不这样做,通常意味着受访者没有太多构建真实世界JavaScript应用程序的经验。如果你不能回答这个问题,那么你只是一个初级开发人员。你实际上已经做了多久并不重要。为了快速理解下面的内容:你能想出两个闭包的常见场景吗?什么是闭包?简而言之,闭包是通过将一个函数绑定到它周围的状态(词法环境)(包)组合结构而形成的。在JavaScript中,闭包是在创建每个函数时形成的。这是基本原理,但我们为什么要关心呢?事实上,闭包允许我们从函数内部访问外部函数的范围,因为它们与它的词法环境相关联。要使用闭包,只需在另一个函数中定义一个函数并将其公开。要公开一个函数,您可以返回它或将它传递给其他函数。内部函数将能够访问外部函数范围内的变量,即使外部函数已完成执行。使用闭包的一个例子闭包的用途之一是实现对象的私有数据。数据隐私使我们能够针对接口而不是实现进行编程。面向接口的编程是一个重要的概念,可以帮助我们创建更健壮的软件,因为实现细节比接口约定更容易更改。“针对接口编程,不要针对实现编程。《设计模式:可重用面向对象软件的要素》在JavaScript中,闭包是用来实现数据隐私的原生机制。当你使用闭包来实现数据隐私时,封装的变量只能在闭包容器函数作用域中使用。你不能绕过对象的授权方法从外部访问这些数据。在JavaScript中,定义在闭包作用域下的任何公共方法都可以访问这些数据。例如:constgetSecret=(secret)=>{return{get:()=>secret};};test('Closureforobjectprivacy.',assert=>{constmsg='.get()应该可以访问闭包。';constexpected=1;constobj=getSecret(1);constactual=obj.get();try{assert.ok(secret,'Thisthrowsanerror.');}catch(e){assert.ok(true,`这些秘密仅适用于特权方法。`);}assert.equal(actual,expected,msg);assert.end();});在上面的例子中,get()方法被定义在getSecret()作用域下,这使得它可以访问getSecret()中的任何变量,所以它是一个授权zed方法。在本例中,它可以访问参数secret。对象不是生成私有数据的唯一方式。闭包也可以用来创建有状态函数,其执行可能由它们自己的内部状态决定。例如:constsecret=(msg)=>()=>msg;//Secret-createclosurewithsecretmessages.//https://gist.github.com/ericelliott/f6a87bc41de31562d0f9//https://jsbin.com/hitusu/edit?html,js,输出//secret(msg:String)=>getSecret()=>msg:Stringconstsecret=(msg)=>()=>msg;test('secret',assert=>{constmsg='secret(在函数式编程中,闭包常用于偏函数应用和柯里化。为了说明这一点,我们先定义一些概念:函数应用:指将参数传递给函数并获取其返回值的过程。偏函数应用:将一些参数传递给函数并返回一个等待接受后续参数的新函数的过程。换句话说,部分函数应用程序是一个将另一个函数作为参数的函数,该函数本身有很多参数,并返回一个参数比它的参数function更少参数的函数。部分函数应用程序预先分配了一些参数,返回的函数在调用时等待传入剩余的参数。部分函数应用程序通过闭包范围预先分配参数。你可以实现一个泛型函数来将部分参数分配给指定的函数,它看起来像这样:更深入的了解上面的表格,可以阅读这里。partialApply接受一个多参数函数,以及我们想要添加到函数前面的参数列表,并返回一个将接受剩余参数的新函数。下面举个例子来说明,假设你有一个求两个数之和的函数:constadd=(a,b)=>a+b;现在你想获得一个函数,可以将传递给它的任何参数都加10,我们可以称它为add10()。add10(5)的结果应该是15。我们的partialApply()函数可以这样做:constadd10=partialApply(add,10);add10(5);在这个例子中,参数10通过闭包作用域被预赋值给add(),这样我们就得到了add10()。现在让我们看看如何实现partialApply()://GenericPartialApplicationFunction//https://jsbin.com/biyupu/edit?html,js,output//https://gist.github.com/ericelliott/f0a8fd662111ea2f569e//partialApply(targetFunction:Function,...fixedArgs:Any[])=>//functionWithFewerParams(...remainingArgs:Any[])constpartialApply=(fn,...fixedArgs)=>{返回函数(...remainingArgs){returnfn.apply(this,fixedArgs.concat(remainingArgs));};};test('add10',assert=>{constmsg='partialApply()shouldpartiallyapplyfunctions'constadd=(a,b)=>a+b;constadd10=partialApply(add,10);constactual=add10(5);constexpected=15;assert.equal(actual,expected,msg);});如您所见,它只是返回一个函数,该函数通过闭包访问传递给partialApply()函数的fixedArgs参数。轮到你试试了。你用闭包做什么?如果您有最喜欢的用例和一些示例,请在评论中告诉我。