DIV CSS 佈局教程網

Javascript作用域
編輯:關於JavaScript     
學習任何編程語言,都逃不過理解變量的作用域。

在javascript中,變量的作用域有全局(window對象)作用域和函數調用作用域。


以下變量具有全局作用域
1. 所有在最外層定義(非函數體內定義)的變量都擁有全局作用域
2. 所有末定義直接賦值的變量,系統會自動聲明為擁有全局作用域的變量
3. 所有window對象的屬性擁有全局作用域


以下變量具有函數作用域
1. 在函數體內部用var定義的變量,這裡要注意一點,只要是在函數裡定義的變量,就算是在最後一句定義,該變量也擁有整個函數的作用域。



特別應該說明的一點是,作用域是層層包含的,最外層是全局作用域,裡面可以包含函數調用作用域,函數調用作用域裡面還可以再有函數作用域,下面,我們看一個簡單的例子:


<mce:script type="text/javascript"><!--
var scope = "global";
window.x = "x-global";

var f1 = function(){
var scope = "function1";
y = "y-golbal";
alert(scope); //will display function1
alert(window.scope); //will display global
alert(x); //will display x-global
}

f1();

alert(scope);//will display global
alert(y); //will display y-golbal
// --></mce:script>


這個例子說明了簡單的全局作用域和函數作用域的區別,我們再思考一下問題,如果函數f1裡面沒有變量scope,而全局作用域裡面有這個變量,會有什麼情況呢?


<mce:script type="text/javascript"><!--
var scope = "global";

var f1 = function(){
//var scope = "function1";
alert(scope); //will display global
alert(window.scope); //will display global

}

f1();

alert(scope);//will display global
// --></mce:script>



為什麼會這樣呢,這是由於javascript的尋找變量的機制造成的。上面己經說了,作用域是層層包含的,上面的這個例子的層次應該是這樣的: 全局作用域->f1的作用域。而javascript查找一個變量時,會從當前作用域往上找,直到找到為止,所以這個例子中,先在f1的作用域找scope,找不到,則到外層的全局作用域找,在全局作用域中找到了scope,就使用該變量,這個例子中,如果在全局作用域也找不到變量scope,則會報錯。
下面我們把這個例子改一下,就會有一個很有趣的現象

<mce:script type="text/javascript"><!--
var scope = "global";

var f1 = function(){

alert(scope); //will display undefined
alert(this.scope); //will display global
var scope = "function1"; //declare scope here
}

f1();

alert(scope);//will display global
// --></mce:script>



這裡還是用javascript查找變量的機制來解釋,首先在f1的作用域裡面找,而f1定義了該變量,所以使用該變量,但是還末賦值,所以是undefined。這裡要說明一點,就是作用域內的變量不管在函數的哪裡聲明,javascript都會在函數運行前在作用域內包含該變量。
下面,我們再看復雜一些的例子:

<mce:script type="text/javascript"><!--
var scope = "global";
var scope2 = "global-scope2"

var f1 = function(){
var scope = "function1";
var scope2 = "function1-scope2";
(function(){ //function2
var scope = "function2";
(function(){ //function3
alert(scope); //will display function2
alert(scope2); //will display function1-scope2
})();

})();


}

f1();
// --></mce:script>



下面,我們還是以javascript查找變量的機制來解釋一下。首先,我們看看作用域的包含情況: 全局作用域-> f1的作用域 ->f2的作用域-> f3的作用域。對於變量scope,先在f3作用域內找,沒找到,往外,在f2作用域裡找到,使用該值,所以打出的值為 function2。對於scope2,先在f3找,沒找到,住外,在f2找,還是沒找到,再往外,在f1找,找到,使用該值,所以打出的值為function1-scope2。

上面的函數都是在定義該函數的作用域裡調用,如f3 在f2定義並調用,f1在全局作用域裡定義並在全局作用域調用,那麼,如果在全局作用域調用,或是在別的函數裡調用f3會有什麼情況呢?下面我們試一下:

<mce:script type="text/javascript"><!--
var scope = "global";
var scope2 = "global-scope2"

var f1 = function(){
var scope = "function1";
var scope2 = "function1-scope2";
return (function(){
var scope = "function2";
return function(){
alert(scope); //will display function2
alert(scope2); //will display function1-scope2
}

})();


}

var f4 = function(fun)
{
fun();
}

var f3 = f1();


f4(f3);
// --></mce:script>



上面的例子我們返回f3,並在f4裡面調用f3,但結果沒變,為什麼呢?這是因為javascript的作用域包含關系是在函數定義的時候確定的,而不是在調用的時候確定的,所以不管在哪調用f3,函數的作用域包含關系都是: 全局作用域->f1->f2->f3。不過上面的這個例子還有另外一個作用域包含關系: 全局作用域->f4的作用域。

最後,還要說明的是,javascript沒有塊作用域,這點跟java,c++,c#,php等都是不同的,所以在循環語句裡面創建的變量也是擁有函數調用作用域或是全局作用域的,並不會有臨時變量存在。

注:
1.在javascript裡,函數也是可以作為數據傳遞的,在上面的例子裡用到了函數作用數據傳遞
2.上面的例子用到了閉包的知識,不清楚的朋友可以了解一下相關的知識
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved