摘要:前端芝士樹中的閉包是怎么一回事筆試問題集錦為什么會有閉包的出現(xiàn)這涉及到作為變量聲明的關鍵詞時所出現(xiàn)的一些問題。另一方面,在函數(shù)外部自然無法讀取函數(shù)內(nèi)的局部變量。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
【前端芝士樹】Js中的閉包是怎么一回事 && 筆試問題集錦 為什么會有閉包的出現(xiàn)?
這涉及到var作為變量聲明的關鍵詞時所出現(xiàn)的一些問題。
比如,var 的 變量提升 以及 函數(shù)級作用域
Javascript語言的特殊之處,就在于函數(shù)內(nèi)部可以直接讀取全局變量。
另一方面,在函數(shù)外部自然無法讀取函數(shù)內(nèi)的局部變量。
需要注意的是,如果在函數(shù)內(nèi)部聲明變量時沒有使用var關鍵詞,實際上聲明的是一個全局變量,如下:
function f1(){ n = 999; } //console.log(n); // ReferenceError: n is not defined f1(); console.log(n); // 999
這里為什么第一處會報錯呢?關于這個問題下面有比較基礎的解釋:
JS的解析過程分為兩個階段:預編譯期(預處理)與執(zhí)行期。
預編譯期 JS會對本代碼塊(兩個script塊互不影響)中的所有var聲明的變量和函數(shù)進行處理(類似與C語言的編譯)
此時處理函數(shù)的只是聲明式函數(shù),而且變量也只是進行了聲明但未進行初始化以及賦值。>執(zhí)行期 會按照代碼塊的順序筑行執(zhí)行
正因為從外部訪問在函數(shù)內(nèi)部進行聲明的局部變量是不可能的,所以出現(xiàn)了閉包這種形式,在函數(shù)內(nèi)部再定義一個函數(shù)。
閉包(Closure)是什么?查閱了一些文章和資料,發(fā)現(xiàn)還是下面的定義最容易理解:
閉包:定義在函數(shù)內(nèi)部的一個函數(shù)。
擴展一些講,可以參考一下阮一峰的講解:
閉包:能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。
俗話說的好,看定義不如看代碼更直觀一些,如下
function f1(){ var n=999; function f2(){ console.log(n); } return f2; } var result=f1(); result(); // 999
如此段代碼所示,f2()就是其中的閉包函數(shù),通過f2()我們可以訪問到f1()內(nèi)部的n。
更常見的一種簡寫形式:
function f1(){ var n=999; return function(){ console.log(n); }; } var result=f1(); result(); // 999閉包的優(yōu)缺點
優(yōu)點:
可以讀取函數(shù)內(nèi)部的變量
讓這些變量的值始終保持在內(nèi)存中。
缺點:
由于閉包會使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會造成網(wǎng)頁的性能問題,在IE中可能導致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
閉包會在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。所以,如果你把父函數(shù)當作對象(object)使用,把閉包當作它的公用方法(Public Method),把內(nèi)部變量當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值。
閉包面試題集錦(持續(xù)更新) 問題一、簡單閉包var a = 1; function foo(){ var a = 2; c = 0; return function () { console.log(a); console.log(b++); console.log(c); } } console.log(a);// 1 //console.log(c); // Reference Error var b = 3; var x = foo(); x(); //2 3 0 console.log(a); // 1 console.log(b); // 4 console.log(c); // 0問題二、閉包的鏈式調(diào)用
function fun(n,o) { console.log(o) return { fun:function(m){ return fun(m,n); } }; } var a = fun(0); a.fun(1); a.fun(2); a.fun(3); var b = fun(0).fun(1).fun(2).fun(3); var c = fun(0).fun(1); c.fun(2); c.fun(3);
看解答前先思考一下會輸出什么哦
【解答】: 首先對函數(shù)進行分析,這個函數(shù)其實是返回了一個對象,{fun:function(){}},里面有一個函數(shù)作為屬性,這個函數(shù)就是閉包,使得函數(shù)內(nèi)部的變量保留在內(nèi)存中。
注意,這里會有一個可能誤解的地方,return {fun:...}里面的fun是fun(n,o)嗎?明白這個區(qū)別后后面就容易多了。
好了,明白大概的原理后,我們來分析這個問題:
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
執(zhí)行a = fun(0),0是作為n傳入的,o沒有參數(shù)傳入,所以輸出undefined,之后,
a = { fun:function(m){ return fun(m,0);//這里的n應該變成了第一次調(diào)用時的參數(shù)n,也就是0 } } 也就是 a = { fun:function(m){ return function(n = m, o = 0) { console.log(o) //輸出0 return { fun:function(m){ return fun(m,n); } }; }; } }
所以無論傳入的m是什么,輸出永遠都是0
最后,輸出結(jié)果如下
var a = fun(0); a.fun(1); a.fun(2); a.fun(3); undefined 0 0 0
搞清楚第一個的過程,第二個的破解關鍵就在于閉包讓函數(shù)內(nèi)部的變量始終保存在內(nèi)存之中。
//b undefined 0 1 2 //c undefined 0 1 1參考文章
《學習Javascript閉包(Closure) - 阮一峰的網(wǎng)絡日志》
《閉包 - 廖雪峰的官方網(wǎng)站》
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/108532.html
摘要:提供了糟糕的支持,而雖然接近標準,但依舊未能完全正確的支持標準。盡管修復了許多的問題,但是依然延續(xù)實現(xiàn)中的其它故障主要是盒模型問題。因此大部分的聲明將觸發(fā)嚴格模式即依據(jù)標準的規(guī)則渲染網(wǎng)頁。 深入理解CSS盒模型、BFC、OffsetWidth&ClientWidth&ScrollWidth 本文將從盒模型開始,一步步涉及一些常見的前端筆試和面試點 主要參考自第一篇文章,然而筆者在讀的時...
摘要:在創(chuàng)建對象不論是普通對象還是函數(shù)對象的時候,都有一個叫做的內(nèi)置屬性,用于指向創(chuàng)建它的構(gòu)造函數(shù)的原型對象,也就是。因為一個普通對象的構(gòu)造函數(shù)所以原型鏈原型鏈的形成是真正是靠而非。參考文章最詳盡的原型與原型鏈終極詳解,沒有可能是。 【前端芝士樹】Javascript的原型、原型鏈以及繼承機制 前端的面試中經(jīng)常會遇到這個問題,自己也是一直似懂非懂,趁這個機會整理一下 0. 為什么會出現(xiàn)原型和...
本文不會過多講解基礎知識,更多說的是在使用useRef如何能擺脫 這個 閉包陷阱 ? react hooks 的閉包陷阱 基本每個開發(fā)員都有遇見,這是很令人抓狂的。 (以下react示范demo,均為react 16.8.3 版本) 列一個具體的場景: functionApp(){ const[count,setCount]=useState(1); useEffect(()=...
摘要:今天同學去面試,做了兩道面試題全部做錯了,發(fā)過來給道典型的面試題前端掘金在界中,開發(fā)人員的需求量一直居高不下。 排序算法 -- JavaScript 標準參考教程(alpha) - 前端 - 掘金來自《JavaScript 標準參考教程(alpha)》,by 阮一峰 目錄 冒泡排序 簡介 算法實現(xiàn) 選擇排序 簡介 算法實現(xiàn) ... 圖例詳解那道 setTimeout 與循環(huán)閉包的經(jīng)典面...
閱讀 917·2021-10-25 09:44
閱讀 1308·2021-09-23 11:56
閱讀 1220·2021-09-10 10:50
閱讀 3156·2019-08-30 15:53
閱讀 2161·2019-08-30 13:17
閱讀 648·2019-08-29 18:43
閱讀 2538·2019-08-29 12:57
閱讀 887·2019-08-26 12:20