摘要:一閉包的概念閉包官方給出的解釋閉包是函數(shù)和聲明該函數(shù)的詞法環(huán)境的組合。解決此類情況的方式使用立即執(zhí)行函數(shù)使用中的這兩種方式的共性就是把變量變成了每個(gè)函數(shù)的局部變量,因此在執(zhí)行閉包的時(shí)候,局部變量不會(huì)發(fā)生變化。
一、閉包的概念
閉包官方給出的解釋:閉包是函數(shù)和聲明該函數(shù)的詞法環(huán)境的組合。
下面我們舉一個(gè)經(jīng)典的且最簡單的閉包demo
function closure(){ var a=4; function clo(){ console.log(a) } clo(); } closure();
從上面的例子中,我們可以看出閉包需要的三基本個(gè)條件是:1.一個(gè)外層函數(shù)。2.一個(gè)內(nèi)部函數(shù)。3.局部變量。
二、閉包的用途要理解閉包的用途首先要理解javascript的特殊的變量作用域。
變量的作用域只有兩種:全部變量和局部變量。而javascript語言中,函數(shù)內(nèi)部可以直接讀取全局變量,但是函數(shù)外部無法讀取函數(shù)內(nèi)部的局部變量。
而我們需要用到的閉包的場景就是:我們需要一個(gè)外部不可以直接訪問一個(gè)函數(shù)內(nèi)部變量的的環(huán)境。因此,通常你使用只有一個(gè)方法的對(duì)象的地方,都可以使用閉包。比如:插件封裝,面向?qū)ο缶幊痰取?/p>
閉包很有用,因?yàn)樗试S將函數(shù)與其所操作的某些數(shù)據(jù)(環(huán)境)關(guān)聯(lián)起來。這顯然類似于面向?qū)ο缶幊獭T诿嫦驅(qū)ο缶幊讨校瑢?duì)象允許我們將某些數(shù)據(jù)(對(duì)象的屬性)與一個(gè)或者多個(gè)方法相關(guān)聯(lián)。
1.DOM中使用閉包實(shí)例
12 14 16 function makeSizer(size) { return function() { document.body.style.fontSize = size + "px"; }; } var size12 = makeSizer(12); var size14 = makeSizer(14); var size16 = makeSizer(16); document.getElementById("size-12").onclick = size12; document.getElementById("size-14").onclick = size14; document.getElementById("size-16").onclick = size16;
2.用閉包模擬私有變量
function closure2(){ var pCounter=0; function changeBy(val){ pCounter += val; } return{ add:function(){ changeBy(1) }, reduce:function(){ changeBy(-1) }, value:function(){ return pCounter } } } var counter1= closure2(); var counter2 = closure2(); console.log(Counter1.value()); Counter1.add(); Counter1.add(); console.log(Counter1.value()); /* logs 2 */ Counter1.reduce(); console.log(Counter1.value()); /* logs 1 */ console.log(Counter2.value()); /* logs 0 */
每次調(diào)用其中一個(gè)計(jì)數(shù)器時(shí),通過改變這個(gè)變量的值,會(huì)改變這個(gè)閉包的詞法環(huán)境。然而在一個(gè)閉包內(nèi)對(duì)變量的修改,不會(huì)影響到另外一個(gè)閉包中的變量。
三、閉包的缺點(diǎn)1.缺點(diǎn)一:變量發(fā)生變化
function arr(){ var res=new Array(); for (var i = 0; i< 10; i++){ res[i]=function(){ console.log(i); } } return res; } var arr1=arr(); arr1[0]();//10 arr1[1]();//10
因?yàn)殚]包里面的函數(shù)調(diào)用發(fā)生在for循環(huán)結(jié)束之后,此時(shí)變量i的值是10,且res組成的閉包集合共用一個(gè)詞法環(huán)境里面的變量i,因此每個(gè)閉包所輸出的值都是10。
解決此類情況的方式:
a.使用立即執(zhí)行函數(shù)
function arr(){ var res=new Array(); for (var i = 0; i< 10; i++){ res[i]=(function (num) { return function(){ console.log(num) } })(i) } return res; } var arr1=arr(); arr1[0]();//0 arr1[1]();//1
b.使用es6中的let
function arr(){ var res=new Array(); for (let i = 0; i< 10; i++){ res[i]=function () { console.log(i) } } return res; } var arr1=arr(); arr1[0]();//0 arr1[1]();//1
這兩種方式的共性就是把變量i,變成了每個(gè)函數(shù)的局部變量,因此在執(zhí)行閉包的時(shí)候,局部變量i不會(huì)發(fā)生變化。
2.缺點(diǎn)二:this指向問題
var obj = { name:"this", getName:function() { return function () { console.log(this.name) } } } var arr= obj.getName(); arr()//undefined
this指向當(dāng)前調(diào)用函數(shù)的上下文,arr函數(shù)創(chuàng)建在全局環(huán)境中,所以在調(diào)用arr時(shí),在非嚴(yán)格模式的瀏覽器環(huán)境中this指向window,在嚴(yán)格模式下this是undefined,而這兩種情況下都沒有一個(gè)全局的name,所以函數(shù)的執(zhí)行結(jié)果為undefined。
3.缺點(diǎn)三:內(nèi)存泄漏
function showId() { var el = document.getElementById("div1") el.onclick = function(){ console.log(el.id) // 這樣會(huì)導(dǎo)致閉包引用外層的el,當(dāng)執(zhí)行完showId后,el無法釋放 } } // 改成下面 function showId() { var el = document.getElementById("app") var id = el.id el.onclick = function(){ console.log(id) // 這樣會(huì)導(dǎo)致閉包引用外層的el,當(dāng)執(zhí)行完showId后,el無法釋放 } el = null // 主動(dòng)釋放el }
當(dāng)閉包中引用了全局變量時(shí),記得在引用完之后進(jìn)行釋放,避免造成內(nèi)存泄漏。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/105069.html
摘要:大名鼎鼎的閉包面試必問。閉包的作用是什么。看到閉包在哪了嗎閉包到底是什么五年前,我也被這個(gè)問題困擾,于是去搜了并總結(jié)下來。關(guān)于閉包的謠言閉包會(huì)造成內(nèi)存泄露錯(cuò)。閉包里面的變量明明就是我們需要的變量,憑什么說是內(nèi)存泄露這個(gè)謠言是如何來的因?yàn)椤? 本文為饑人谷講師方方原創(chuàng)文章,首發(fā)于 前端學(xué)習(xí)指南。 大名鼎鼎的閉包!面試必問。請(qǐng)用自己的話簡述 什么是「閉包」。 「閉包」的作用是什么。 首先...
摘要:也正因?yàn)檫@個(gè)閉包的特性,閉包函數(shù)可以讓父函數(shù)的數(shù)據(jù)一直駐留在內(nèi)存中保存,從而這也是后來模塊化的基礎(chǔ)。只有閉包函數(shù),可以讓它的父函數(shù)作用域永恒,像全局作用域,一直在內(nèi)存中存在。的本質(zhì)就是如此,每個(gè)模塊文件就是一個(gè)大閉包。 為什么會(huì)有閉包 js之所以會(huì)有閉包,是因?yàn)閖s不同于其他規(guī)范的語言,js允許一個(gè)函數(shù)中再嵌套子函數(shù),正是因?yàn)檫@種允許函數(shù)嵌套,導(dǎo)致js出現(xiàn)了所謂閉包。 function...
摘要:當(dāng)初看這個(gè)解釋有點(diǎn)懵逼,理解成閉包就是函數(shù)中的函數(shù)了。里的閉包最近不滿足于只干前端的活,開始用起了。里的閉包最近在學(xué)習(xí)語言,讓我們來看一下語言里的閉包。在中,閉包特指將函數(shù)作為值返回的情況,被返回的函數(shù)引用了生成它的母函數(shù)中的變量。 本人開始接觸編程是從js開始的,當(dāng)時(shí)網(wǎng)上很多人說閉包是難點(diǎn),各種地方對(duì)閉包的解釋也是千奇百怪。如今開始接觸js以外的各種編程語言,發(fā)現(xiàn)不光是js,php、...
摘要:當(dāng)初看這個(gè)解釋有點(diǎn)懵逼,理解成閉包就是函數(shù)中的函數(shù)了。里的閉包最近不滿足于只干前端的活,開始用起了。里的閉包最近在學(xué)習(xí)語言,讓我們來看一下語言里的閉包。在中,閉包特指將函數(shù)作為值返回的情況,被返回的函數(shù)引用了生成它的母函數(shù)中的變量。 本人開始接觸編程是從js開始的,當(dāng)時(shí)網(wǎng)上很多人說閉包是難點(diǎn),各種地方對(duì)閉包的解釋也是千奇百怪。如今開始接觸js以外的各種編程語言,發(fā)現(xiàn)不光是js,php、...
摘要:但閉包的情況不同嵌套函數(shù)的閉包執(zhí)行后,,然后還在被回收閉包會(huì)使變量始終保存在內(nèi)存中,如果不當(dāng)使用會(huì)增大內(nèi)存消耗。每個(gè)函數(shù),不論多深,都可以認(rèn)為是全局的子作用域,可以理解為閉包。 閉包(closure)是Javascript語言的一個(gè)難點(diǎn),也是它的特色,很多高級(jí)應(yīng)用都要依靠閉包實(shí)現(xiàn)。 閉包的特性 閉包有三個(gè)特性: 1.函數(shù)嵌套函數(shù) 2.函數(shù)內(nèi)部可以引用外部的參數(shù)和變量 3.參數(shù)和變量不會(huì)...
摘要:內(nèi)部的稱為內(nèi)部函數(shù)或閉包函數(shù)。過度使用閉包會(huì)導(dǎo)致性能下降。,閉包函數(shù)分為定義時(shí),和運(yùn)行時(shí)。循環(huán)會(huì)先運(yùn)行完畢,此時(shí),閉包函數(shù)并沒有運(yùn)行。閉包只能取得外部函數(shù)中的最后一個(gè)值。事件綁定種的匿名函數(shù)也是閉包函數(shù)。而對(duì)象中的閉包函數(shù),指向。 閉包概念解釋: 閉包(也叫詞法閉包或者函數(shù)閉包)。 在一個(gè)函數(shù)parent內(nèi)聲明另一個(gè)函數(shù)child,形成了嵌套。函數(shù)child使用了函數(shù)parent的參數(shù)...
閱讀 2060·2021-11-22 13:52
閱讀 984·2021-11-17 09:33
閱讀 2716·2021-09-01 10:49
閱讀 2851·2019-08-30 15:53
閱讀 2663·2019-08-29 16:10
閱讀 2437·2019-08-29 11:31
閱讀 1357·2019-08-26 11:40
閱讀 1872·2019-08-26 10:59