JavaScript 閉包
什么是閉包
閉包,官方對閉包的解釋是:一個擁有許多變量和綁定了這些變量的環(huán)境的表達式(通常是一個函數(shù)),因而這些變量也是該表達式的一部分。閉包的特點:
1. 作為一個函數(shù)變量的一個引用,當函數(shù)返回時,其處于激活狀態(tài)。
2. 一個閉包就是當一個函數(shù)返回時,一個沒有釋放資源的棧區(qū)。
簡單的說,Javascript允許使用內(nèi)部函數(shù)---即函數(shù)定義和函數(shù)表達式位于另一個函數(shù)的函數(shù)體內(nèi)。而且,這些內(nèi)部函數(shù)可以訪問它們所在的外部函數(shù)中聲明的所有局部變量、參數(shù)和聲明的其他內(nèi)部函數(shù)。當其中一個這樣的內(nèi)部函數(shù)在包含它們的外部函數(shù)之外被調(diào)用時,就會形成閉包。
閉包的幾種寫法和用法
第一種寫法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文網(wǎng)(php.cn)</title> <script type="text/javascript"> function Circle(r) { this.r = r; } Circle.PI = 3.14159; Circle.prototype.area = function() { return Circle.PI * this.r * this.r; } var c = new Circle(1.0); alert(c.area()); </script> </head> <body> </body> </html>
這種寫法沒什么特別的,只是給函數(shù)添加一些屬性。
第二種寫法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文網(wǎng)(php.cn)</title> <script type="text/javascript"> var Circle = function() { var obj = new Object(); obj.PI = 3.14159; obj.area = function( r ) { return this.PI * r * r; } return obj; } var c = new Circle(); alert( c.area( 1.0 ) ); </script> </head> <body> </body> </html>
這種寫法是聲明一個變量,將一個函數(shù)當作值賦給變量。
第三種寫法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文網(wǎng)(php.cn)</title> <script type="text/javascript"> var Circle = new Object(); Circle.PI = 3.14159; Circle.Area = function( r ) { return this.PI * r * r; } alert( Circle.Area( 1.0 ) ); </script> </head> <body> </body> </html>
這種方法最好理解,就是new 一個對象,然后給對象添加屬性和方法。
第四種寫法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文網(wǎng)(php.cn)</title> <script type="text/javascript"> var Circle={ "PI":3.14159, "area":function(r){ return this.PI * r * r; } }; alert( Circle.area(1.0) ); </script> </head> <body> </body> </html>
這種方法使用較多,也最為方便。var obj = {}就是聲明一個空的對象
Javascript閉包的用途
事實上,通過使用閉包,我們可以做很多事情。比如模擬面向?qū)ο蟮拇a風格;更優(yōu)雅,更簡潔的表達出代碼;在某些方面提升代碼的執(zhí)行效率。
1、匿名自執(zhí)行函數(shù)
2、結(jié)果緩存
3、封裝
4、實現(xiàn)類和繼承
JavaScript 內(nèi)嵌函數(shù)
所有函數(shù)都能訪問全局變量。
實際上,在 JavaScript 中,所有函數(shù)都能訪問它們上一層的作用域。
JavaScript 支持嵌套函數(shù)。嵌套函數(shù)可以訪問上一層的函數(shù)變量。
該實例中,內(nèi)嵌函數(shù) plus() 可以訪問父函數(shù)的 counter 變量:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文網(wǎng)(php.cn)</title> </head> <body> <p id="demo">0</p> <script> document.getElementById("demo").innerHTML = add(); function add() { var counter = 0; function plus() {counter += 1;} plus(); return counter; } </script> </body> </html>
如果我們能在外部訪問 plus() 函數(shù),這樣就能解決計數(shù)器的困境。
我們同樣需要確保 counter = 0 只執(zhí)行一次。
這里就需要閉包。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文網(wǎng)(php.cn)</title> </head> <body> <button type="button" onclick="myFunction()">計數(shù)!</button> <p id="demo">0</p> <script> var add = (function () { var counter = 0; return function () {return counter += 1;} })(); function myFunction(){ document.getElementById("demo").innerHTML = add(); } </script> </body> </html>
實例解析
變量 add 指定了函數(shù)自我調(diào)用的返回字值。
自我調(diào)用函數(shù)只執(zhí)行一次。設(shè)置計數(shù)器為 0。并返回函數(shù)表達式。
add變量可以作為一個函數(shù)使用。非常棒的部分是它可以訪問函數(shù)上一層作用域的計數(shù)器。
這個叫作 JavaScript 閉包。它使得函數(shù)擁有私有變量變成可能。
計數(shù)器受匿名函數(shù)的作用域保護,只能通過 add 方法修改。
閉包是可訪問上一層函數(shù)作用域里變量的函數(shù),即便上一層函數(shù)已經(jīng)關(guān)閉。