摘要:函數(shù)在執(zhí)行的時候執(zhí)行函數(shù),將當(dāng)前的變量對象由于當(dāng)前的環(huán)境是函數(shù),所以將其活動對象作為變量對象添加到作用域鏈的前端。此時,由于在執(zhí)行,而作用域鏈也存在,所以可以在作用域鏈上進行查找,去訪問的變量。
一、現(xiàn)狀
閉包是jser繞不過的坎,一直在都在說,套用 simpson 的話來說:JavaScript中閉包無處不在,你只需要能夠識別并擁抱它。
閉包是基于詞法作用域書寫代碼時的自然結(jié)果,你甚至不需要為了利用它們而有意識的去創(chuàng)建閉包。閉包的創(chuàng)建和使用在你的代碼中隨處可見。你缺少的只是根據(jù)你的意愿來識別、擁抱和影響閉包的思維環(huán)境
二、什么是閉包(closure)當(dāng)函數(shù)可以記住并訪問所在的詞法作用域時,就產(chǎn)生了閉包。即使函數(shù)是在當(dāng)前詞法作用域之外執(zhí)行 --《你不知道的js》(上卷)
閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù) --《JavaScript高級程序設(shè)計》
先來看一個例子:
例子1:
function foo(){ var a = 2; function bar(){ console.log(a); // 2 } bar(); } foo()
這是閉包嗎?
這個代碼從技術(shù)上來說是,但也可以說不是。準確的來說bar()對a的引用的方法是詞法作用域的查找規(guī)則。我們再來看:
例子2:
function foo(){ var a = 2; function bar(){ console.log(a) } return bar; } var baz = foo(); baz(); // 2, 這就是閉包了
在例2中,我們將bar()函數(shù)本身當(dāng)做一個值類型進行傳遞,函數(shù)bar()能夠訪問foo()的內(nèi)部作用域。在這個例子中,它在自己定義的詞法作用域以外的地方執(zhí)行。
三、怎么形成的要了解清楚,得先了解幾個概念
作用域鏈(scope chain)
詞法作用域
詞法作用域每個函數(shù)都有自己的執(zhí)行環(huán)境。這個環(huán)境可以訪問外部環(huán)境,以此類推。每個環(huán)境能訪問到的標識符集合,稱之為 作用域,也就是詞法作用域。
作用域鏈(scope chain)將作用域一層一層的嵌套,就形成了作用域鏈
如下,通常我們都希望foo()在執(zhí)行完成以后,整個的內(nèi)部作用域都被銷毀。因為我們知道引擎有垃圾回收機制用來釋放不再使用的內(nèi)存空間。由于看上去foo()的內(nèi)容不會再被使用,所以很自然的想到會對其回收。但是,事實上內(nèi)部作用域依然存在
var globalVar = 10; function foo() { var fooVar = 20; function bar() { var barVar = 30; return globalVar + fooVar + barVar; } return bar; } var baz = foo(); baz();
如上,用一張圖表示
這個作用域鏈在函數(shù)創(chuàng)建的時候就保存起來了。
baz()函數(shù)在執(zhí)行的時候(執(zhí)行bar()函數(shù)),將當(dāng)前的變量對象(由于當(dāng)前的環(huán)境是函數(shù),所以將其活動對象作為變量對象)添加到作用域鏈的前端。此時,由于bar()在執(zhí)行,而作用域鏈也存在,所以可以在作用域鏈上進行查找,去訪問foo()的變量。
四、閉包的應(yīng)用場景有哪些創(chuàng)建私有變量或函數(shù)
五、閉包的缺點閉包中的值是存在于內(nèi)存中,濫用的話會導(dǎo)致內(nèi)存消耗過大
閉包經(jīng)典問題
// 函數(shù)作用:希望它返回一個數(shù)組。該數(shù)組的元素為遍歷的索引值 function hello(){ var res = []; for (var i = 0,len = 5;i < len;i++){ res[i] = function () { return i; } } return res; }
返回的結(jié)果跟我們期待的不一樣,因為:閉包保存的是整個變量對象,而不是每個變量。
解決方案:
function hello(){ var res = []; for (var i = 0,len = 5;i < len;i++){ res[i] = (function(i){ return i; })(i) } return res; }
這里,沒有沒有把閉包直接賦值給數(shù)組。而是定義了一個匿名函數(shù),并且將立即執(zhí)行該匿名函數(shù)的結(jié)果賦值給數(shù)組,由于參數(shù)是按值傳遞的,所以會將當(dāng)前值傳給參數(shù)num。
參考資料:《你不知道的js》(中卷)、《JavaScript高級程序設(shè)計》
完
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/92653.html
摘要:歡迎來我的個人站點性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動及頁面渲染優(yōu)化理論寫法對壓縮率的影響唯快不破應(yīng)用的個優(yōu)化步驟進階鵝廠大神用直出實現(xiàn)網(wǎng)頁瞬開緩存網(wǎng)頁性能管理詳解寫給后端程序員的緩存原理介紹年底補課緩存機制優(yōu)化動 歡迎來我的個人站點 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動 scroll 及頁面渲染優(yōu)化 理論 | HTML寫法...
摘要:歡迎來我的個人站點性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動及頁面渲染優(yōu)化理論寫法對壓縮率的影響唯快不破應(yīng)用的個優(yōu)化步驟進階鵝廠大神用直出實現(xiàn)網(wǎng)頁瞬開緩存網(wǎng)頁性能管理詳解寫給后端程序員的緩存原理介紹年底補課緩存機制優(yōu)化動 歡迎來我的個人站點 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動 scroll 及頁面渲染優(yōu)化 理論 | HTML寫法...
摘要:歡迎來我的個人站點性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動及頁面渲染優(yōu)化理論寫法對壓縮率的影響唯快不破應(yīng)用的個優(yōu)化步驟進階鵝廠大神用直出實現(xiàn)網(wǎng)頁瞬開緩存網(wǎng)頁性能管理詳解寫給后端程序員的緩存原理介紹年底補課緩存機制優(yōu)化動 歡迎來我的個人站點 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動 scroll 及頁面渲染優(yōu)化 理論 | HTML寫法...
摘要:在內(nèi)部,理所當(dāng)然能訪問到局部變量,但當(dāng)作為的返回值賦給外的全局變量時,神奇的事情發(fā)生了在全局作用域中訪問到了,這就是閉包。而閉包最神奇的地方就是能在一個函數(shù)外訪問函數(shù)中的局部變量,把這些變量用閉包的形式放在函數(shù)中便能避免污染。 一、閉包是什么? 《JavaScript高級程序設(shè)計》中寫道:閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù),如果用下定義的觀點看,這句話就是說閉包是函數(shù),我...
摘要:但是函數(shù)返回了內(nèi)部函數(shù),內(nèi)部函數(shù)會隨時訪問變量所以垃圾回收機制是不會回收函數(shù)的內(nèi)部作用域的,這就是閉包的含義。也就是函數(shù)在定義的詞法作用域以外的地方被調(diào)用,閉包使得函數(shù)可以繼續(xù)訪問定義時的詞法作用域。 初學(xué)JavaScript閉包時,閉包這個概念在我眼里及其的神秘,也不知道這個東西在講什么,尤其某些地方的閉包概念定義的非常抽象,屬于那種本來你可能明白這個概念,看了反而又把你給繞糊涂...
閱讀 1500·2021-11-17 09:33
閱讀 1267·2021-10-11 10:59
閱讀 2900·2021-09-30 09:48
閱讀 1909·2021-09-30 09:47
閱讀 3032·2019-08-30 15:55
閱讀 2343·2019-08-30 15:54
閱讀 1499·2019-08-29 15:25
閱讀 1653·2019-08-29 10:57