DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> JavaScript基礎知識 >> JS閉包新手入門總結
JS閉包新手入門總結
編輯:JavaScript基礎知識     
/**************作用域*****************/
首先理解閉包,就必須先理解JS特殊的變量作用域。

變量的作用域無非就是兩種:全局變量和局部變量。

JS的特殊之處就是在於函數內部可以直接讀取局部變量。
另一方面,在函數外部自然無法讀取函數內的局部變量。、

需要注意的的是函數內部聲明變量的時候,一定要使用var命令。如果不用的話,其實聲明了一個全局變量。

如何從外部讀取局部變量,就是在函數的內部,在定義一個函數。

既然f2可以讀取f1中的局部變量,那麼只要把f2作為返回值,我們不就可以在f1外部讀取它的內部變量了嗎!


Js代碼

  function f1(){

    n=999;//全局變量

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999



/************* 閉包**************/
1.概念
閉包就是能夠讀取其他函數內部變量的函數。


由於在JS中,只有函數內部的子函數才能讀取局部變量,因此可以把閉包簡單理解成“定義在一個函數內部的函數”。


所以,在本質上,閉包就是將函數內部和函數外部連接起來的一座橋梁。

2.用途
閉包最大的用處有兩個,一個便是可以讀取函數內部的變量。另一個就是讓這些變量的值始終保持在內存中。

3.使用閉包的注意點
由於閉包會使得函數值的變量都被保存在內存中,內存的消耗會很大,所以不能濫用閉包,否則會使網頁的性能降低,在IE中可能會導致內存洩露問題。解決辦法就是,在退出函數之前,將不適用的局部變量全部刪除。

閉包會在父函數的外部,改變父函數內部變量的值,所以,如果你把父函數當做對象object使用,把閉包當做它的公用方法,把內部變量當做它的私有屬性,這時,不能隨便改變父函數內部變量的值。



/************* 閉包的應用機制**************/
通過保護變量的安全實現JS私有屬性和私有方法(不能被外部訪問)
function Constructor(...){
var that = this;
var membername = value;
function membername(...){...}
}
以上三點是閉包最基本的應用場景,很多經典案列都源於此。



/************* JS的垃圾回收garbage collection機制**************/
在JS中,如果一個對象不再被引用,那麼這個對象就會被GC回收。如果兩個對象互相引用,而不是被第三者所引用,那麼兩個互相引用的對象也會被回收,因為函數a被b引用,b又被a外的c引用,這就是為什麼函數a執行後不會被回收的原因。



/************* 總結**************/
當內部函數在定義它的作用域的 外部被引用時,就創建了該內部函數的閉包,如果內部函數引用了位於外部函數的變量,當外部函數調用完畢後,這些變量在內存不會被釋放,因為閉包需要他們。

官方的解釋:閉包是一個擁有許多變量和綁定了這些變量的環境的表達式,通常是一個函數,其實通俗來講,JS中所有的function都是一個閉包,不過一般來說,嵌套的function所產生的閉包更為強大,也就是我們大部分所謂的閉包。



如圖所示,當在函數b中訪問一個變量的時候,搜索順序是:

先搜索自身的活動對象,如果存在則返回,如果不存在將繼續搜索函數a的活動對象,依次查找,直到找到為止。
如果b存在prototype原型對象,則在查找完自身的活動對象後先查找自身的原型對象,再繼續查找,這就是JS中的變量查找機制。
如果整個作用域鏈都無法找到,也就是找到object時,也沒有,則返回undefined。

在文中會提到兩個重要的詞語,函數的定義與執行,文中提到的函數的作用域是在定義函數時候就已經確定,而不是在執行的時候確定。
例如:

function f(x) {
var g = function () { return x; }
return g;
}
var h = f(1);
alert(h());
這段代碼中變量h指向了f中的那個匿名函數(由g返回)。

假設函數h的作用域是在執行alert(h())確定的,那麼此時h的作用域鏈是:h的活動對象->alert的活動對象->window對象。
假設函數h的作用域是在定義時確定的,就是說h指向的那個匿名函數在定義的時候就已經確定了作用域。那麼在執行的時候,h的作用域鏈為:h的活動對象->f的活動對象->window對象。
如果第一種假設成立,那輸出值就是undefined;如果第二種假設成立,輸出值則為1。

運行結果證明了第2個假設是正確的,說明函數的作用域確實是在定義這個函數的時候就已經確定了。
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved