自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Javascript中的暗物質(zhì):閉包

開(kāi)發(fā) 前端
如何在javascript實(shí)現(xiàn)數(shù)據(jù)的保護(hù)呢?閉包就是實(shí)現(xiàn)它的利器,這需要我們放下普通的對(duì)象,理解一下javascript的工作原理。

1. 詭異的閉包

javascript 中有一個(gè)特殊的特性 - 閉包,對(duì)于 .NET 程序員來(lái)說(shuō),比較熟悉的是面向?qū)ο蟮某绦蛟O(shè)計(jì) OOP,  而來(lái)自函數(shù)式語(yǔ)言的閉包則顯得比較詭異,許多程序員對(duì)它敬而遠(yuǎn)之。

對(duì)于閉包我們還是要從函數(shù)式語(yǔ)言的特點(diǎn)說(shuō)起。

不知道你有沒(méi)有發(fā)現(xiàn),在 javascript 中沒(méi)有 public ,private 之類的關(guān)鍵字,也沒(méi)有 class ,雖然也存在對(duì)象一說(shuō),但是對(duì)象的地位遠(yuǎn)遠(yuǎn)沒(méi)有在 C# 中是一等公民,在 js 中,沒(méi)有對(duì)象你也可以一樣寫程序。它只是一種數(shù)據(jù)的表示形式而已,可有也可無(wú)。

2. 閉包何來(lái)?

如何在 javascript 實(shí)現(xiàn)數(shù)據(jù)的保護(hù)呢?閉包就是實(shí)現(xiàn)它的利器,這需要我們放下普通的對(duì)象,理解一下 javascript 的工作原理。

在 javascript 中,可以在函數(shù)中定義新的函數(shù),這種嵌套函數(shù)還可以作為函數(shù)的返回值,被外部的變量所引用。在普通的程序設(shè)計(jì)語(yǔ)言中,比如 C 中,雖然也存在函數(shù)指針的概念,但是,所謂的函數(shù)指針僅僅是一段代碼的地址而已,而 javascript 中返回的函數(shù)引用,則不限于此。

在 C 語(yǔ)言中,在函數(shù)運(yùn)行的時(shí)候,局部變量是保存在堆棧中的,函數(shù)執(zhí)行完畢,系統(tǒng)所做的是彈出堆棧。

實(shí)際上,在 javascript 中,函數(shù)每次執(zhí)行的時(shí)候,注意是運(yùn)行時(shí),系統(tǒng)會(huì)同時(shí)創(chuàng)建一個(gè)此次函數(shù)運(yùn)行的環(huán)境對(duì)象,而此次運(yùn)行期間的局部變量則關(guān)聯(lián)在這個(gè)環(huán)境對(duì)象上,在普通不返回函數(shù) 的普通函數(shù)中,函數(shù)執(zhí)行完畢,則環(huán)境對(duì)象也一起釋放。而如果函數(shù)返回了定義在外部函數(shù)中的嵌套函數(shù),那么,這個(gè)環(huán)境對(duì)象將不會(huì)釋放,也就是說(shuō),這個(gè)時(shí)候, 返回了一個(gè)看得見(jiàn)的函數(shù)對(duì)象,還附帶了一個(gè)看不見(jiàn)的暗物質(zhì) - 外部函數(shù)的環(huán)境對(duì)象。

看得見(jiàn)的函數(shù)對(duì)象加上隱含的環(huán)境對(duì)象就是閉包。

這個(gè)環(huán)境對(duì)象只能通過(guò)這個(gè)函數(shù)隱式訪問(wèn),我們并沒(méi)有它的引用,也無(wú)法直接訪問(wèn)它。結(jié)果就是實(shí)現(xiàn)了信息的隱藏。

3. 實(shí)現(xiàn)私有的數(shù)據(jù)

考慮下面的代碼

  1. function outer() { 
  2.     var name = "Alice"
  3.     var inner = function () { 
  4.         return name; 
  5.     } 
  6.     return inner; 
  7.  
  8. var fn = outer(); 
  9. alert(fn()); 

 在這個(gè)例子中,看起來(lái)簡(jiǎn)單的 fn 函數(shù)背后,其實(shí)暗藏了在執(zhí)行 outer 函數(shù)時(shí)期創(chuàng)建的環(huán)境對(duì)象,所以通過(guò) fn 可以得到 Alice 這個(gè)名字,而且沒(méi)有其他的渠道允許得到這個(gè)名字。

4. 為什么數(shù)據(jù)搞亂了?

再看另外一個(gè)經(jīng)典的例子。

  1. <body> 
  2.     <div> 
  3.         <a href="#">Click Me!</a> 
  4.         <a href="#">Click Me!</a> 
  5.         <a href="#">Click Me!</a> 
  6.     </div> 
  7.     <script type ="text/javascript"
  8.         function main(links) { 
  9.             for (var i = 0; i < links.length; i++) { 
  10.                 links[i].onclick = function () { 
  11.                     alert(i + 1); 
  12.                 } 
  13.             } 
  14.         }; 
  15.         main(document.getElementsByTagName("a")); 
  16.     </script> 
  17.  
  18. </body> 

彈出的是多少呢?感覺(jué)有三次循環(huán),應(yīng)該彈出 1, 2, 3。運(yùn)行一下,你會(huì)看到實(shí)際上是 4, 4, 4!

是不是非常詭異?

從閉包的角度來(lái)說(shuō),則非常簡(jiǎn)單,main 函數(shù)執(zhí)行了幾次呢?只有一次,在執(zhí)行的時(shí)候創(chuàng)建了一個(gè)閉包對(duì)象,其中引用了定義在 main 中的局部變量 i,在循環(huán)體中,實(shí)際上創(chuàng)建了三個(gè)內(nèi)部函數(shù),它們引用的都是同一個(gè)環(huán)境對(duì)象。這些函數(shù)注冊(cè)到鏈接的 onclick 事件上,其實(shí)也就是已經(jīng)傳出了函數(shù) main,所以,main 的環(huán)境對(duì)象也就悄悄地成為了暗物質(zhì),而循環(huán)完成之后 i 已經(jīng)最終被賦予了 3 這個(gè)值,三個(gè)函數(shù)訪問(wèn)的是同一個(gè)環(huán)境對(duì)象中的 i, 所以,在點(diǎn)擊鏈接的時(shí)候看到 4 這個(gè)結(jié)果也就正常了。

5. 解鈴還需系鈴人

如果希望得到的是 1, 2, 3 這個(gè)結(jié)果又該怎么辦呢?

我們可以定義一個(gè)內(nèi)部函數(shù),讓它執(zhí)行三次,這個(gè)將會(huì)創(chuàng)建三個(gè)對(duì)應(yīng)的環(huán)境對(duì)象,我們可以使得這三個(gè)環(huán)境對(duì)象包含不同的值。

  1. function main(links) { 
  2.     var inner = function (elem, i) { 
  3.         elem.onclick = function () { 
  4.             alert(i + 1); 
  5.         }; 
  6.     }; 
  7.     for (var i = 0; i < links.length; i++) { 
  8.         var elem = links[i]; 
  9.         inner(elem, i); 
  10.     } 
  11. }; 

由于 inner 函數(shù)執(zhí)行了三次,所以將會(huì)創(chuàng)建三個(gè)不同的環(huán)境對(duì)象,每個(gè)環(huán)境對(duì)象中的 i 都是不同的值。這樣注冊(cè)到 onclick 中的函數(shù)就可以訪問(wèn)到不同的值了。

閉包的概念

這里,我們可以看一下閉包的概念了。來(lái)自 Wiki 的說(shuō)明是這樣的

在計(jì)算機(jī)科學(xué)中,閉包(Closure)是詞法閉包(Lexical Closure)的簡(jiǎn)稱,是引用了自由變量的函數(shù)。這個(gè)被引用的自由變量將和這個(gè)函數(shù)一同存在,即使已經(jīng)離開(kāi)了創(chuàng)造它的環(huán)境也不例外。所以,有另一種說(shuō)法認(rèn)為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體。

原文鏈接:http://www.cnblogs.com/haogj/archive/2012/11/28/2793535.html

責(zé)任編輯:林師授 來(lái)源: 博客園
相關(guān)推薦

2012-04-26 09:45:52

程序員

2011-05-12 18:26:08

Javascript作用域

2021-02-21 16:21:19

JavaScript閉包前端

2016-09-14 09:20:05

JavaScript閉包Web

2009-07-24 17:30:37

Javascript閉

2011-05-25 14:48:33

Javascript閉包

2020-10-14 15:15:28

JavaScript(

2023-10-26 07:47:35

JavaScript代碼變量

2020-02-12 16:58:15

JavaScript前端技術(shù)

2010-06-23 10:24:42

Javascript閉

2016-09-18 20:53:16

JavaScript閉包前端

2017-09-14 13:55:57

JavaScript

2023-09-06 16:55:33

JavaScript閉包

2011-03-02 12:33:00

JavaScript

2020-09-29 06:39:38

智能

2009-03-17 15:36:29

JavaScript循環(huán)事件

2017-05-22 16:08:30

前端開(kāi)發(fā)javascript閉包

2021-01-13 11:25:12

JavaScript閉包函數(shù)

2021-12-06 07:15:48

Javascript作用域閉包

2016-11-01 09:18:33

Python閉包
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)