(~ ̄(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