irpas技术客

JavaScript闭包 - 面试重灾区,如何应对?_java小白翻身

网络 676

1.闭包-面试重灾区

最近面试的过程中,但凡问到JavaScript闭包的时候,一脸懵逼的情况的占多数。

闭包这个东西,你说它重要吧,确实很重要,毕竟这是很多前端框架广泛使用的开发技巧。你说他不重要吧,也确实没那么重要,因为我们开发项目基本都是套用现有的框架,在框架的范围里面写代码,很少会用到闭包。

可是,耐不住面试经常要问啊。

这一节,我们就来聊聊闭包的话题!

2.什么情况会产生闭包

先看一个例子:

function f(){ let a = 1; return function(){ console.log(a); } } f()()

a是函数f内部的一个变量,按理说函数结束后,外面就没法访问到a了。

可是假如我们用一个函数访问到a,然后再把这个函数返回出去,就延续了a的生命周期。

上面代码的结果是1。

不仅如此,我们还可以在外面反复地操作a。

3.闭包将产生幽灵般的鬼魅变量

上面的例子中,我们把a变量悄悄地送出了函数f,接下来我们可以对它进行反复蹂躏!

function f(){ let a = 1; return function(increment){ a += increment; console.log(a); } } f()(1)

答案是2,可见,我们可以在外面对a变量进行操作。下面思考一个问题,假如我多次操作会怎样?

var inner = f(); inner(1); inner(1); inner(1);

答案

?可见,多次操作的话,操作的是同一个a变量,这个a变量就如同鬼魅一般,你在外面看不到他,他却真实存在着。

4.闭包可以和对象结合起来用

直接看下面的例子,有一定的实战意义

var obj = {} function f(){ let a = 1; obj.num = a; obj.get = function(){ return a; } obj.set = function(v){ a = v; } } f()

这个代码和之前的有不同,它没有在函数f中直接返回另一个函数,而是给外面的obj对象赋予了一些属性和方法,很神奇吧,可这是语法允许的。

函数f被运行后,那么obj.num的值想必大家一看就知道是1

那假如我这么做呢?

obj.num += 1;

?这样一来,obj.num就等于2

但是obj.get()得到的值是多少?

还是1,这是因为a是基本类型的数字1,而?obj.num = a?其实是值拷贝,我们没法通过改变num的大小去同步改变a,他们是两个变量了。而?obj.get,obj.set 操作的才是真正的a

上面我们说?a是基本类型的数字1,而?obj.num = a?其实是值拷贝 ,那如果a是对象类型,就可以操作了。

let a = {}; obj.a = a; obj.get = function(){ return a; } obj.set = function(v){ a = v; }

好了,从这个例子中,我们不难发现,闭包的最大作用就是延续函数内部某些变量的生命周期。但是也正因为此,闭包可能会引发一些内存泄漏的问题。不过,大部分情况,这点内存泄漏真的无伤大雅。

可能有的同学会说,我不用闭包也可以啊,大不了在obj里面设置一个属性a,一样的。

在这个例子中,确实是的。

可是,在某些特殊的时候,用闭包是真的很有必要。

5.闭包的实战 - Vue数据绑定?

在Vue中,我们知道,会有一个初始化过程,这个过程会对data中的所有属性进行挟持,以便触发watcher更新。以下是简化的代码

var data = { username:'', password:'' } for(let key in data){ Object.defineProperty(data,key,{ set(v){ data[key] = v }, get(){ return data[key] } }) }

这个代码乍一看没啥问题,可是当我们给username赋值,就会触发set方法

?报错是因为发生了循环引用,set被重复触发。

同样的,get也会报错

?

?这可怎么办,我们是不是必须得有一个临时变量,来保存当前属性的value呢?

像这样

for(let key in data){ let value = data[key] Object.defineProperty(data,key,{ set(v){ value = v }, get(){ return value } }) }

瞬间完美了。

?按理说,value是for循环中的一个临时变量而已,因为用的是let,所以只在当前作用域有效。而这个临时的value因为被set和get方法访问到了,于是其生命周期也得以延续!

所以,我对闭包的理解就是:函数访问了外部的变量,并且这个函数会在未来的某个时刻用到这个变量,就是闭包。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #JavaScript闭包 #面试重灾区 #如何应对 #可是耐不住面试经常要问啊