1. 程式人生 > >js變量的作用域詳解

js變量的作用域詳解

gpo 第一個 pos html fin step 參數 類型 rip

JavaScript中的變量作用域問題對一些初學前端的人來說可能是一個很頭疼的問題,但是我相信,等你看完這篇文章之後你會有一個相對明確的理解

首先,我們來看看下面的兩段代碼輸出結果分別是什麽。

代碼一:

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

代碼二:

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

這裏就涉及到了全局變量以及局部變量的問題,代碼一func()中的a只是執行了聲明操作,並未賦值,所以第一次彈出的是undefined,緊接著它就對a進行了賦值操作,將2賦值給a,因此代碼一的輸出結果是undefined 2,代碼二中因為func()這個局部作用域中在第一個alert之前是沒有對a進行聲明賦值操作的,所以調用的還是外部全局作用域中的a的值,所以代碼二的輸出結果是1 2;

我們再來看下面這段代碼:

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

它的輸出值又是多少呢?1 2 1?No,並不是,結果是undefined 2 1,為什麽呢?這裏其實涉及到了變量的預解析。上述代碼其實就相當於下面這段代碼:

var a =1;  
function func(){  
    var a;      //預解析
    alert(a);  
    var a = 2;  
    alert(a);  
}  
func();  
alert(a);

以上是作用域的黃金守則第一條: 變量的查找是就近原則,去尋找var定義的變量,當就近沒有找到的時候就去查找外層。


我們來看下面的代碼:

 var a = 10;
 function funcA(){//step-4
    alert(a);//step-5->執行alert,此時只能找到外面的a=10故彈框10
 }
 function funcB(){//step-2
     var a = 20;
     funcA();//step-3
 }
 //定義了函數沒啥用,調用才是真格的所以這裏是step-1
bbb();//step-1

彈出的結果是10;

接下來看這段代碼:

function
funcA(){ var a=b=10; } funcA(); alert(a); //直接報錯,a is not defined alert(b);

而當我把alert(a)註釋的時候:

function funcA(){
    var a=b=10;
}
funcA();
//alert(a);
alert(b);    //彈出10

這是為什麽呢?var a=b=10這種寫法在函數內,b其實是全局變量,a當然是局部變量,執行完funcA(),在全局範圍內alert(a),當然是undefined,alert(b)是10。

以上是作用域黃金守則第二條: js沒有塊級作用域(你可以自己閉包或其他方法實現),只有函數級作用域,函數外面的變量函數裏面可以找到,函數裏面的變量外面找不到。


var a=10;
function funcA(){
    alert(a);
    var a=20;
}
funcA();    //彈出10

還有:傳參時,基本類型傳值,引用類型傳引用。(但是重新賦值之後就不是這樣了喔):

var a = 5;
var b = a;
b +=3;
alert(a);//5
var a = [1,2,3];
var b=a;
b.push(4);
alert(a);//[1,2,3,4];

上面代碼沒有問題,但是下面就不一樣啦。

var a=[1,2,3,];
vae b=a;
b=[1,2,3,4];
alert(a); //[1,2,3]

因為b被重新賦值了,不指向a了。

此外,參數與變量的作用域是相似的:

var a=10;
function func(a){
    a += 3;
}
func(a);
alert(a); //10

對比上下這兩個:

var a=10;
function func(a){
    a += 3;
    alert(a);
}
func(a); //13

上面是參數是基本類型,只傳了值進去,下面的傳個引用類型:(同樣也包含重新賦值的情況)

var a=[1,2,3];
function func(a){
    a = [1,2,3,4];
}
func(a); 
alert(a); //[1,2,3]

var a=[1,2,3];
function func(a){
    a.push(4);
}
func(a); 
alert(a); //[1,2,3,4]

以上是作用域黃金守則第三條: 當參數跟局部變量重名時,優先級是等同的。

(本文引用:https://www.cnblogs.com/skylar/p/3986087.html)

js變量的作用域詳解