天天看點

JS閉包、作用域

今天同僚出了個JS題目,如下:

function dosomething()

{

var x = 1 ;

if ( true )

{

var x = 2 ;

alert(x);

}

alert(x);

}

很多人都以為顯示的是"2"和"1",理由是2個x的聲明是在不同的作用域裡面,

但是實際的結果其實為"2","2",這個是為什麼呢?

在網上查閱資料給出了解釋:

作用域

ECMAScript 隻有公用作用域

對 ECMAScript 讨論上面這些作用域幾乎毫無意義,因為 ECMAScript 中隻存在一種作用域 - 公用作用域。

ECMAScript 中的所有對象的所有屬性和方法都是公用的。是以,定義自己的類和對象時,必須格外小心。記住,所有屬性和方法預設都是公用的!

閉包

ECMAScript 最易讓人誤解的一點是,它支援閉包(closure)。

閉包,指的是詞法表示包括不被計算的變量的函數,也就是說,函數可以使用函數之外定義的變量。

簡單的閉包執行個體

在 ECMAScript 中使用全局變量是一個簡單的閉包執行個體。請思考下面這段代碼:

var sMessage = "hello world";      

function sayHelloWorld() {

alert(sMessage);

}

sayHelloWorld();

在上面這段代碼中,腳本被載入記憶體後,并沒有為函數 sayHelloWorld() 計算變量 sMessage 的值。該函數捕獲 sMessage 的值隻是為了以後的使用,也就是說,解釋程式知道在調用該函數時要檢查 sMessage 的值。sMessage 将在函數調用 sayHelloWorld() 時(最後一行)被指派,顯示消息 "hello world"。

複雜的閉包執行個體

在一個函數中定義另一個會使閉包變得更加複雜。例如:

var iBaseNum = 10;      

function addNum(iNum1, iNum2) {

function doAdd() {

return iNum1 + iNum2 + iBaseNum;

}

return doAdd();

}

這裡,函數 addNum() 包括函數 doAdd() (閉包)。内部函數是一個閉包,因為它将擷取外部函數的參數 iNum1 和 iNum2 以及全局變量 iBaseNum 的值。 addNum() 的最後一步調用了 doAdd(),把兩個參數和全局變量相加,并傳回它們的和。

這裡要掌握的重要概念是,doAdd() 函數根本不接受參數,它使用的值是從執行環境中擷取的。

轉載于:https://www.cnblogs.com/tonywang711/archive/2010/12/13/1904556.html

繼續閱讀