JavaScript使用閉包模仿塊級作用域操作示例
本文實例講述了JavaScript使用閉包模仿塊級作用域操作。分享給大家供大家參考,具體如下:
在閱讀這篇文章之前,建議先閱讀JavaScript的作用域鏈以及JavaScript閉包。
正如閉包的定義一樣:“閉包指的是有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)”, 閉包最大的意義就在于閉包可以對另一個函數(shù)作用域的變量進行訪問,由此,閉包可以延伸出一系列的用法。
模仿塊級作用域
JavaScript沒有塊級作用域的概念。這意味著在塊語句中定義的變量,實際上是包含在函數(shù)中而非語句中創(chuàng)建的。從作用域鏈的角度來理解是,所有在函數(shù)內(nèi)定義的變量(所有,也就是說塊語句中定義的變量也包含在內(nèi))都會在這個函數(shù)執(zhí)行時所創(chuàng)建的函數(shù)的活動對象中,因此從函數(shù)內(nèi)的所有變量定義開始,就可以在函數(shù)內(nèi)部隨處訪問它,閉包也可以通過作用域鏈訪問它。
例子:
function outputNumbers(count){ for(var i = 0; i < count; i++){ console.log(i); // 0, 1, ... count - 1 } console.log(i); // count }
C++, JAVA等語言中,變量i只會在for循環(huán)的語句塊(block)中有定義,循環(huán)一旦結(jié)束,變量i就會被銷毀??墒窃贘avaScript中,變量i是定義在outputNumbers()的活動對象中,因此從函數(shù)內(nèi)的所有變量定義開始,就可以在函數(shù)內(nèi)部隨處訪問它,閉包也可以通過作用域鏈訪問它。即使像下面這樣重新聲明同一個變量,也不會改變它的值。
function outputNumbers(count){ for(var i = 0; i < count; i++){ console.log(i); // 0, 1, ... count - 1 } var i; // redeclare i console.log(i); // count }
JavaScript從來不管是否多次聲明了同一個變量;遇到這種情況,JavaScript只會對后續(xù)的聲明視而不見(不過會執(zhí)行后續(xù)聲明中的變量初始化),將其當(dāng)成一個賦值語句。
函數(shù)包裝器可以用來模仿塊作用域并避免這個問題。
函數(shù)包裝器就是創(chuàng)建并立即調(diào)用一個函數(shù)。
(function(){ console.log("Hello World!"); })();
這段代碼直接輸出”Hello World”, 這就是一個函數(shù)包裝器。
函數(shù)包裝器的作用:
1. 立即執(zhí)行函數(shù)中的代碼,又不會再內(nèi)存中留下對該函數(shù)的引用;
2. 函數(shù)內(nèi)部的所有變量都會被立即銷毀(除非將這些變量賦值給了包含作用域中的變量)。
當(dāng)在函數(shù)內(nèi)部使用函數(shù)包裝器的時候,此時函數(shù)包裝器就是一個閉包,有權(quán)訪問外部環(huán)境中的所有變量。
function outputNumbers(count){ (function(){ //塊級作用域 for(var i = 0; i < count; i++){ console.log(i); // 0, 1, ... count - 1 } })(); console.log(i); // error }
在函數(shù)包裝器中可以訪問外部環(huán)境outputNumbers()
的變量count,打印0, 1, … count - 1,但是在函數(shù)包裝器執(zhí)行完畢之后,再訪問變量i就會拋出錯誤,因為i是在函數(shù)包裝器中定義的,outputNumbers()
函數(shù)無法訪問。
無論在什么地方,如果只需要一些臨時變量,就可以使用塊級作用域!
使用函數(shù)包裝器這種閉包可以減少閉包過多占用內(nèi)存的問題。因為沒有指向匿名函數(shù)的引用, 所以只要函數(shù)包裝器執(zhí)行完畢,就可以立即銷毀其作用域鏈了。
函數(shù)包裝器這種技術(shù)經(jīng)常在全局作用域中被用在函數(shù)外部,從而限制想全局作用域中添加過多的變量和函數(shù)。一般來說,我們都應(yīng)該盡量少向全局作用域中添加變量和函數(shù)。過多的全局變量和函數(shù)很容易導(dǎo)致命名沖突。通過創(chuàng)建塊級作用域,每個開發(fā)人員既可以使用自己的變量,有不必擔(dān)心搞亂全局作用域。例如:
(function(){ var now = new Date(); if (now.getMonth() == 0 && now.getDate() == 1) { console.log("Happy new year"); } })();
將這段代碼放在全局作用域中,可以用來確定哪天是一月一日。其中變量now現(xiàn)在是匿名函數(shù)中的局部變量,避免了在全局變量中創(chuàng)建。
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《javascript面向?qū)ο笕腴T教程》、《JavaScript錯誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運算用法總結(jié)》
希望本文所述對大家JavaScript程序設(shè)計有所幫助。
相關(guān)文章
javascript讓setInteval里的函數(shù)參數(shù)中的this指向特定的對象
話說阿里巴巴今年的校園招聘有一道題目考了一個知識點,那就是setInterval的參數(shù)函數(shù)里的this指向.2010-01-01Echarts折線圖設(shè)置線條顏色及線條以下代碼示例
最近項目需要,一直在使用Echarts視圖,現(xiàn)在遇到一個要修改echarts折線圖顏色的需求,下面這篇文章主要給大家介紹了關(guān)于Echarts折線圖設(shè)置線條顏色及線條以下區(qū)域漸變顏色的相關(guān)資料,需要的朋友可以參考下2024-02-02JavaScript 原型學(xué)習(xí)總結(jié)
每個對像都有一個隱慝的屬性用于指向到它的父對像(構(gòu)造對像的函數(shù))的原型(這里稱為父原型或隱式原型),并從中繼承它的屬性和方法2010-10-10