前言
準確來說,閉包是基于正常的垃圾回收處理機制下的。也就是說,一般情況一個函數(shù)(函數(shù)作用域)執(zhí)行完畢,里面聲明的變量會全部釋放,被垃圾回收器回收。但閉包利用一個技巧,讓作用域里面的變量,在函數(shù)執(zhí)行完之后依舊保存沒有被垃圾回收處理掉。
閉包
定義
MDN定義
javascriptkit
詞法作用域
閉包的三大特點為:
1、函數(shù)嵌套函數(shù)
2、內部函數(shù)可以訪問外部函數(shù)的變量
3、參數(shù)和變量不會被回收。
作用域鏈
函數(shù)在執(zhí)行的過程中,先從自己內部找變量如果找不到,再從創(chuàng)建當前函數(shù)所在的作用域(詞法作用域)去找, 以 此往上注意找的是變量的當前的狀態(tài)
作用域鏈的博客
函數(shù)連同它作用域鏈上的要找的這個變量,共同構成閉包
一般情況下使用閉包主要是為了
封裝數(shù)據(jù) 暫存數(shù)據(jù)一個典型的閉包案例
function car(){ var speed = 0 function fn(){ speed++ console.log(speed) } return fn}var speedUp = car()speedUp() //1speedUp() //2當函數(shù)內部沒有執(zhí)行以下的代碼時
function fn(){ speed++ console.log(speed) }return fn在代碼執(zhí)行完成后,函數(shù)內部的局部變量speed就會被銷毀,由于全局標量speedUp一直存在(除非關閉當前頁面,否則全局變量一直存在),那么函數(shù)內部的作用域就沒有辦法被銷毀,里面有東西一直被使用,這點與瀏覽器的垃圾回收機制相仿,當我們執(zhí)行speedUp(),他會在函數(shù)的詞法作用域下去尋找,函數(shù)里面又返回了一個fn,因而形成閉包,簡單的理解為
var speed = 0function fn(){ speed++ console.log(speed)}這一段代碼形成一個閉包,如果不return fn,那函數(shù)內部的局部變量就會被銷毀。
我們可以看看上述代碼利用立即執(zhí)行語句和立即執(zhí)行函數(shù)可以怎么演變:
function car(){ var speed = 0 function fn(){ speed++ console.log(speed) } return fn}var speedUp = car()//1function car(){ var speed = 0 return function (){ speed++ console.log(speed) }}var speedUp = car()//2function car(speed){ return function (){ speed++ console.log(speed) }}var speedUp = car(3)//3function car(){ var speed = arguments[0] return function (){ speed++ console.log(speed) }}var speedUp = car()//4function car(){ var speed = 0 return function (){ speed++ console.log(speed) }}//5 car可以不寫,則為匿名函數(shù) var speedUp = (function car(speed){ return function (){ speed++ console.log(speed) }})(3)閉包的相關案例
如下代碼輸出多少?如果想輸出3,那如何改造代碼?
var fnArr = [];for (var i = 0; i < 10; i ++) { fnArr[i] = function(){ return i };}console.log( fnArr[3]() ) // 10
新聞熱點
疑難解答
圖片精選