DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> 深入淺析javascript中的作用域(推薦)
深入淺析javascript中的作用域(推薦)
編輯:關於JavaScript     

所謂的作用域,可以簡單理解為一個可以讀、寫的范圍(區域),有些js經驗的同學可能會說:"js沒有塊級作用域",js除了全局作用域外,只有函數可以創建作用域。作用域的一個好處就是可以隔離變量。

我們通過一些例子來幫助我們理解js中的作用域。

 alert(a);
 var a = 1; 

如果對作用域一點不了解的同學可能會說 alert的是1或者報錯;但實際上是undefined;

說到這裡,我們首先說一下js逐行解析代碼之前做的一些准備工作,

js在逐行讀代碼之前,會做一些“預解析”工作,會先提前找到一些”小東西”,當然”js解析器“不會隨便找一些數據的,它會根據var,function,參數來找。

”js解析器“它比較”懶“,在正式運行代碼之前都會給var聲明的變量賦值為undefined,也就是var a = undefined;會把整個函數看作一個代碼塊,不去管裡邊有多少代碼。參數等到後邊例子中會說。

當所有准備工作都做好後,“JS解析器”就開始逐行執行代碼了,現在我們來分析開始的這個例子就很容易明白為什麼是undefined了。

再來看下邊這個例子

 alert(a);
 var a = 1;
 alert(a);
 var a = 2;
 alert(a); 

我們來一點點分析這個

首先 ”預解析“: 解析器會找var

讀到第二行時 a = undefined;

讀到第四行時 依然 a = undefined;

正式逐行執行代碼:

第一行 alert:undefined 

第二行 a = 1;

第三行 alert:1;

第五行 alert:2

接著看下邊這個例子

 alert(a); 
 var a = 1;
 alert(a); 
 function a (){ alert(2); }
 alert(a); 
 var a = 3; 
 alert(a); 
 function a (){ alert(4); }
 alert(a);

我們依然來一點點分析這個

首先 ”預解析“: 解析器會找var function;

讀到第二行時 a = undefined;

讀到第四行時 a = function a (){ alert(2);} //所有的函數,在正式運行代碼之前,都是整個函數塊;變量遇到重名的,只留一個變量,如果變量和函數重名,就只留下函數。

讀到第六行時,a = function a (){ alert(2);}

讀到第八行時,a = function a (){ alert(4);}

正式逐行執行代碼:

第一行 alert: function a (){ alert(4);} 

第二行 a = 1; //表達式可以修改預解析的值!

第三行 alert:1;

第四行 函數沒有調用,略過;

第五行 alert:1;

第六行 a = 3;

第七行 alert:3

第八行 函數沒有調用,略過;

第九行 alert:3

如圖所示:

繼續看例子:

var a = 1;
function fn1(){
 alert(a); //undefined   
 var a = 2;
}
fn1();
alert(a); //1

首先 ”預解析“: 解析器會找var function

讀到第一行時 a = undefined;

讀到第二行時 fn1 = function fn1 (){alert(2);var a = 2;}

正式逐行執行代碼: 第一行 a = 1;

第六行 函數調用,進入函數作用域 在函數作用域內依舊是先預解析,再逐行執行

  函數內預解析:a = undefined;

  執行:alert:undefined;

  a = 2; //此時的a僅為函數作用域中的a,不會影響全局中的a

函數執行完畢,回到全局作用域;

第七行 alert:1;

繼續:

var a = 1;
function fn1(){
 alert(a); //1  
 a = 2;
}
fn1();
alert(a); //2

這個例子上邊那個例子唯一的區別就是函數中的a沒有var,只分析其中關鍵的地方

在函數作用域中 第三行alert(a),由於函數中沒有var a,所以"解析器"會到函數的作用域的上一級作用域去尋找a(作用域上下級關系的確定就看函數是在哪個作用域下創建的,在哪個作用域下創建,就是哪個作用域的下級),此時函數的上一級是全局作用域,在全局作用域中,a = 1,所以此時第三行 alert:1,接著第四行,a = 2賦值,依然是函數作用域中沒有a, 所以在上一級作用域,也就是全局作用域中找到a,修改全局作用域中的a, 所以會使全局作用域中的a = 2, 因此第七行 alert:2;

這點要理解清楚,注意有無var的區別。

接著來:

 var a = 1;
 function fn1(a){
 alert(a); //undefined 
 a = 2;
 }
 fn1();
 alert(a); // 1

這個例子和上一個的區別就是多了個參數,參數的作用相當於局部變量,也就是在函數中預解析會有var a = undefined,所以第三行 alert:undefined,第四行 a = 2 改的是函數作用域中的a,不影響全局中的a,第七行alert:1;

接著:

var a = 1;
function fn1(a){
alert(a); // 1
a = 2;
}
fn1(a);
alert(a); // 1

這個例子又與上一個有些區別,在第六行函數調用時傳了個實參進去,第六行函數實參的a是全局變量a = 1的1,函數執行時,第二行 a = 1,所以第三行alert:1,第七行alert:1。

注意這幾個例子之間的區別,別混淆了。

再來一個:

var a = 1;
function en(){
var a = 2;
fn();
}
function fn(){
alert(a); //1
}
en();

fn中的a未聲明,要到創建這個函數的那個作用域中取值——是“創建”,而不是“調用”這個函數的作用域中。

PS:JavaScript中的作用域和上下文概念

javascript中的作用域(scope)和上下文(context)是這門語言的獨到之處,這部分歸功於他們帶來的靈活性。每個函數有不同的變量上下文和作用域。這些概念是javascript中一些強大的設計模式的後盾。然而這也給開發人員帶來很大困惑。下面全面揭示了javascript中的上下文和作用域的不同,以及各種設計模式如何使用他們。

上下文 vs 作用域

首先需要澄清的問題是上下文和作用域是不同的概念。多年來我注意到許多開發者經常將這兩個術語混淆,錯誤的將一個描述為另一個。平心而論,這些術語變得非常混亂不堪。

每個函數調用都有與之相關的作用域和上下文。從根本上說,范圍是基於函數(function-based)而上下文是基於對象(object-based)。換句話說,作用域是和每次函數調用時變量的訪問有關,並且每次調用都是獨立的。上下文總是關鍵字 this 的值,是調用當前可執行代碼的對象的引用。

以上所述是小編給大家介紹的javascript中的作用域(推薦),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對網站的支持!

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved