摘要:一閉包的概念閉包官方給出的解釋閉包是函數和聲明該函數的詞法環境的組合。解決此類情況的方式使用立即執行函數使用中的這兩種方式的共性就是把變量變成了每個函數的局部變量,因此在執行閉包的時候,局部變量不會發生變化。
一、閉包的概念
閉包官方給出的解釋:閉包是函數和聲明該函數的詞法環境的組合。
下面我們舉一個經典的且最簡單的閉包demo
function closure(){ var a=4; function clo(){ console.log(a) } clo(); } closure();
從上面的例子中,我們可以看出閉包需要的三基本個條件是:1.一個外層函數。2.一個內部函數。3.局部變量。
二、閉包的用途要理解閉包的用途首先要理解javascript的特殊的變量作用域。
變量的作用域只有兩種:全部變量和局部變量。而javascript語言中,函數內部可以直接讀取全局變量,但是函數外部無法讀取函數內部的局部變量。
而我們需要用到的閉包的場景就是:我們需要一個外部不可以直接訪問一個函數內部變量的的環境。因此,通常你使用只有一個方法的對象的地方,都可以使用閉包。比如:插件封裝,面向對象編程等。
閉包很有用,因為它允許將函數與其所操作的某些數據(環境)關聯起來。這顯然類似于面向對象編程。在面向對象編程中,對象允許我們將某些數據(對象的屬性)與一個或者多個方法相關聯。
1.DOM中使用閉包實例
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 */
每次調用其中一個計數器時,通過改變這個變量的值,會改變這個閉包的詞法環境。然而在一個閉包內對變量的修改,不會影響到另外一個閉包中的變量。
三、閉包的缺點1.缺點一:變量發生變化
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
因為閉包里面的函數調用發生在for循環結束之后,此時變量i的值是10,且res組成的閉包集合共用一個詞法環境里面的變量i,因此每個閉包所輸出的值都是10。
解決此類情況的方式:
a.使用立即執行函數
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,變成了每個函數的局部變量,因此在執行閉包的時候,局部變量i不會發生變化。
2.缺點二:this指向問題
var obj = { name:"this", getName:function() { return function () { console.log(this.name) } } } var arr= obj.getName(); arr()//undefined
this指向當前調用函數的上下文,arr函數創建在全局環境中,所以在調用arr時,在非嚴格模式的瀏覽器環境中this指向window,在嚴格模式下this是undefined,而這兩種情況下都沒有一個全局的name,所以函數的執行結果為undefined。
3.缺點三:內存泄漏
function showId() { var el = document.getElementById("div1") el.onclick = function(){ console.log(el.id) // 這樣會導致閉包引用外層的el,當執行完showId后,el無法釋放 } } // 改成下面 function showId() { var el = document.getElementById("app") var id = el.id el.onclick = function(){ console.log(id) // 這樣會導致閉包引用外層的el,當執行完showId后,el無法釋放 } el = null // 主動釋放el }
當閉包中引用了全局變量時,記得在引用完之后進行釋放,避免造成內存泄漏。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105069.html
摘要:大名鼎鼎的閉包面試必問。閉包的作用是什么。看到閉包在哪了嗎閉包到底是什么五年前,我也被這個問題困擾,于是去搜了并總結下來。關于閉包的謠言閉包會造成內存泄露錯。閉包里面的變量明明就是我們需要的變量,憑什么說是內存泄露這個謠言是如何來的因為。 本文為饑人谷講師方方原創文章,首發于 前端學習指南。 大名鼎鼎的閉包!面試必問。請用自己的話簡述 什么是「閉包」。 「閉包」的作用是什么。 首先...
摘要:當初看這個解釋有點懵逼,理解成閉包就是函數中的函數了。里的閉包最近不滿足于只干前端的活,開始用起了。里的閉包最近在學習語言,讓我們來看一下語言里的閉包。在中,閉包特指將函數作為值返回的情況,被返回的函數引用了生成它的母函數中的變量。 本人開始接觸編程是從js開始的,當時網上很多人說閉包是難點,各種地方對閉包的解釋也是千奇百怪。如今開始接觸js以外的各種編程語言,發現不光是js,php、...
摘要:當初看這個解釋有點懵逼,理解成閉包就是函數中的函數了。里的閉包最近不滿足于只干前端的活,開始用起了。里的閉包最近在學習語言,讓我們來看一下語言里的閉包。在中,閉包特指將函數作為值返回的情況,被返回的函數引用了生成它的母函數中的變量。 本人開始接觸編程是從js開始的,當時網上很多人說閉包是難點,各種地方對閉包的解釋也是千奇百怪。如今開始接觸js以外的各種編程語言,發現不光是js,php、...
摘要:內部的稱為內部函數或閉包函數。過度使用閉包會導致性能下降。,閉包函數分為定義時,和運行時。循環會先運行完畢,此時,閉包函數并沒有運行。閉包只能取得外部函數中的最后一個值。事件綁定種的匿名函數也是閉包函數。而對象中的閉包函數,指向。 閉包概念解釋: 閉包(也叫詞法閉包或者函數閉包)。 在一個函數parent內聲明另一個函數child,形成了嵌套。函數child使用了函數parent的參數...
閱讀 2053·2021-11-22 13:52
閱讀 976·2021-11-17 09:33
閱讀 2708·2021-09-01 10:49
閱讀 2841·2019-08-30 15:53
閱讀 2659·2019-08-29 16:10
閱讀 2432·2019-08-29 11:31
閱讀 1343·2019-08-26 11:40
閱讀 1866·2019-08-26 10:59