(~ ̄(OO) ̄)ブ,闭包,一个面试长问的问题,本白也迷糊了好久。慢慢不断地有了本身的一点认识,这里分享一下~~~
废话很少说,先看题:javascript
var output = (function () { var x = y = 7; return [ function () { console.log(x) }, function () { console.log(y); } ] })(); for (var i = 0; i < 2; i++) { output[i](); } console.log(++y); console.log(++x);
结果是什么呢???
你们能够先本身想一下,而后来听我分析(xiache)(#^.^#);
首先咱们从for循环开始看起,循环了2次,分别执行了outputp[0]();outputp[1]();
首先outputp会执行return出一个数组,数组中有两个方法,因此outputp[0]();outputp[1]();会执行数组中的两个方法。java
第一次听到闭包,别人给个人解释就是,函数中输出函数。
哈哈,简单粗暴的理解,不过也对,这样确实是造成了闭包。关于闭包,咱们就要说到javascript的做用域,咱们都知道,js中无非就是全局变量和局部变量。在js中,函数的内部均可以访问的全局变量的值,但在函数外部没法获取内部的值。但有一个方法能够帮咱们在外部调取内部的值,没错,这就是闭包~~~
咱们先继续看这道题,我将一步步解释。
这个是函数内部return函数,造成了闭包。因此咱们在外部能够获取到 x,y的值。没错也就是咱们能够用outputp[0]();outputp[1]();来获取,也就是会打印 7 7;es6
通常的函数,没有return的时候,函数执行完成后也就会关闭了,但闭包会return出来一个函数,因此这个函数不能关闭,因此咱们能够利用这个特性,这也就是我所认为的闭包。(萌新,否求指);面试
最后的两行console.log(++y);console.log(++x); 这里咱们回到 var x = y = 7;
等用于 y = 7;var x = y; 因此,y实际上是个全局变量。而x是局部变量。
console.log(++y) 会输出8 由于全局变量在哪均可以访问到
console.log(++x) 会报错 Uncaught ReferenceError: x is not defined
有的同窗可能要问,既然闭包 也就是x的值还在内存中,为何访问不到呢,由于咱们以前说过,函数外部没法获取内部的值,因此直接调用x是获取不到的,闭包是利用outputp[0]()这种return出的函数调用其父的值x,y才获取的到。数组
闭包有什么用呢,本萌新在实战中也用到过几回,但毕竟经验不足。这里就说两点吧。安全
for(var i = 0; i < 8;i++) { setTimeout(function(){ console.log(i) },500) }
这个会输出 8 个 8,面试题考烂了的。 如何输出0/1/2/3/4/5/6/7呢
只要将var i 变成 let i 就能够了。 若是不用es6语法怎么作呢? 这样:闭包
for (var i = 0; i < 8; i++) { (function(i){ setTimeout(function (){ console.log(i); },1000); })(i); }
这个也是利用闭包的原理,函数内部能够看父亲函数的值,由于父函数中有子函数,因此每次for循环i的值都在内存中,没有变。函数
第二点就是利用闭包的特色,增长某些key的安全性。 好比有一个很重要的信息 “楼主可真是个小机灵鬼”,在一个函数内部,咱们在外部想到用它,但不想任何人均可以随便调到,由于这个信息很重要。这样咱们就能够这样:加密
function getKey(){ var key = "楼主可真是个小机灵鬼"; return { _xxx : (function(){ return key; })() } }; console.log(getKey()._xxx)
key咱们想本身全局的调用,但不想让同事调用。_xxx能够是一个加密的字符串,我就能够这样写这样我全局的均可以用到。
这就是本小白对闭包的理解,否佬指(不对的地方,麻烦大佬指出);
最后祝你们身体健康,谢谢~~~code