摘要:首先引用文檔的一句話作為開頭閉包是函數和聲明該函數的詞法環境的組合。這個環境包含了這個閉包創建時所能訪問的所有局部變量。
首先引用 MDN 文檔的一句話作為開頭
閉包是函數和聲明該函數的詞法環境的組合。閉包的概念
當一個函數被 return 的時候,這個函數內部的詞法作用域中的變量是可以被外界訪問到的,外層函數執行完畢時被銷毀,但由于內部函數作為值返回出去,這些值得以保存下來,存儲在內存中,也就是私有性。
一個基本的例子:
// 來自 MDN function makeFunc() { var name = "DOG"; function displayName() { alert(name); } return displayName; } var myFunc = makeFunc(); myFunc();
閉包是由函數以及創建該函數的詞法環境組合而成。這個環境包含了這個閉包創建時所能訪問的所有局部變量。執行 makeFunc 時創建的 displayName 函數實例的引用,而 displayName 實例仍可訪問其詞法作用域中的變量,即可以訪問到 name 。由此,當 myFunc 被調用時,name 仍可被訪問。
閉包的應用 私有屬性在 JavaScript 中,是沒有原生支持私有屬性的(據說現在已經有了提議),但是我們可以使用閉包來創建一個私有屬性。
// 來自 MDN var makeCounter = function() { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, value: function() { return privateCounter; } } }; var counter = makeCounter(); console.log(counter.privateCounter); // undefined console.log(counter.value()); // 0存儲變量
function func() { var x = 100; return { function() { return x; } } } var m = func(); //運行函數,變量 x 被 m 引用
此時 m 引用了變量 x ,所以函數執行后 x 不會被釋放,可以把比較重要或者計算耗費很大的值存在 x 中,只需要第一次計算賦值后,就可以通過 m 函數引用 x 的值,不必重復計算,同時也不容易被修改。
導致的問題看一個例子:
var a = []; for(var i = 0; i < 10; i++) { a[i] = () => { return i; }; } a[6](); //10
在這個簡單的函數中,變量 i 是在 for 循環中定義的,如果是在 C++ 或者 Java 中,這樣定義的變量,一旦循環結束,變量也就隨之銷毀,i 的作用范圍只在循環這個小塊,就稱為塊級作用域。在 JavaScript中,沒有這樣的塊級作用域。所以上一段代碼其實相當于:
var a = []; var i = 0; for(; i < 10; i++) { a[i] = () => { return i; }; } a[6](); //10
這樣就很好理解了。由于匿名函數里面沒有 i 這個變量,在函數執行的時候,這個 i 他要從父級函數中尋找,而父級函數中的 i 在for 循環中,當找到這個 i 的時候,是 for 循環已經循環完畢,所以所得與預想不一致。
改進:
var a = []; for(var i = 0; i < 10; i++) { a[i] = (() => { return i; })(); } a[6]; // 6總結
看到了一段很有用的話:
當一個子函數被創建時,是父函數的執行導致的,所以當子函數創建時,父函數已經處于執行階段,所以父函數的執行上下文已經創建了。同時,因為子函數也在父函數的局部變量作用域內,所以,子函數在創建的時候,除了要引用全局上下文,也需要引用父函數的執行上下文。當一個子函數執行時,因為它同樣是函數,所以它同樣需要創建自己的執行上下文,當它返回的時候,同樣也只解除屬性中對自身執行上下文的引用,對父函數的執行上下文的引用并沒有解除,這意味著,父函數的執行上下文與子函數本身共存亡了。只要子函數還存在引用,垃圾收集器就不會銷毀它們所在的執行上下文。另外,因為父函數的局部變量并不在全局上下文中,所以它只能在子函數的變量解析中被訪問,自然而然就相當于它們是子函數私有的了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99739.html
摘要:大名鼎鼎的閉包面試必問。閉包的作用是什么。看到閉包在哪了嗎閉包到底是什么五年前,我也被這個問題困擾,于是去搜了并總結下來。關于閉包的謠言閉包會造成內存泄露錯。閉包里面的變量明明就是我們需要的變量,憑什么說是內存泄露這個謠言是如何來的因為。 本文為饑人谷講師方方原創文章,首發于 前端學習指南。 大名鼎鼎的閉包!面試必問。請用自己的話簡述 什么是「閉包」。 「閉包」的作用是什么。 首先...
摘要:完美的閉包,對,閉包就這么簡單。這僅僅是閉包的一部分,閉包利用函數作用域達到了訪問外層變量的目的。此時一個完整的閉包實現了,的垃圾回收機制由于閉包的存在無法銷毀變量。 1.閉包是指有權訪問另一個函數作用域中的變量的函數。 上面這段話來自 javascript 高級程序設計 第三版 P178 。作者說閉包是一個函數,它有訪問另一個函數作用域中的變量的能力。 2.函數訪問它被創建時所處的...
摘要:到底什么是閉包這個問題在面試是時候經常都會被問,很多小白一聽就懵逼了,不知道如何回答好。上面這么說閉包是一種特殊的對象。閉包的注意事項通常,函數的作用域及其所有變量都會在函數執行結束后被銷毀。從而使用閉包模塊化代碼,減少全局變量的污染。 閉包,有人說它是一種設計理念,有人說所有的函數都是閉包。到底什么是閉包?這個問題在面試是時候經常都會被問,很多小白一聽就懵逼了,不知道如何回答好。這個...
摘要:但是閉包也不是什么復雜到不可理解的東西,簡而言之,閉包就是閉包就是函數的局部變量集合,只是這些局部變量在函數返回后會繼續存在。可惜的是,并沒有提供相關的成員和方法來訪問閉包中的局部變量。 (收藏自 技術狂) 前言:還是一篇入門文章。Javascript中有幾個非常重要的語言特性——對象、原型繼承、閉包。其中閉包 對于那些使用傳統靜態語言C/C++的程序員來說是一個新的語言特性。本文將...
摘要:也許最好的理解是閉包總是在進入某個函數的時候被創建,而局部變量是被加入到這個閉包中。在函數內部的函數的內部聲明函數是可以的可以獲得不止一個層級的閉包。 前言 總括 :這篇文章使用有效的javascript代碼向程序員們解釋了閉包,大牛和功能型程序員請自行忽略。 譯者 :文章寫在2006年,可直到翻譯的21小時之前作者還在完善這篇文章,在Stackoverflow的How do Java...
閱讀 1990·2021-09-22 16:05
閱讀 9255·2021-09-22 15:03
閱讀 2880·2019-08-30 15:53
閱讀 1698·2019-08-29 11:15
閱讀 903·2019-08-26 13:52
閱讀 2348·2019-08-26 11:32
閱讀 1798·2019-08-26 10:38
閱讀 2562·2019-08-23 17:19