js中變量含(參數、數組)作用域傳遞問題


    js沒有塊級作用域(你可以自己閉包或其他方法實現),只有函數級作用域和全局作用域,函數外面的變量函數里面可以找到使用,函數里面的變量外面無法訪問到。

寫這個是因為ES6中的一個例子開始的。首先看下例子

var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10

var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
這兩個實例的區別在於定義i的時候,循環先執行完后,等待調用執行的時候,i才會被賦值給函數體內,等於是循環先給數組賦值完畢后。等待調用。而不是循環的時候就把i的值log出來!
兩個例子一個用了var 一個用let定義變量。 let是有塊級作用域,因此每次循環體的i都是不同且獨立的
上面代碼中,變量ivar命令聲明的,在全局范圍內都有效,所以全局只有一個變量i
每一次循環,變量i的值都會發生改變,而循環內被賦給數組a的函數內部的console.log(i),里面的i指向的就是全局的i。也就是說,所有數組a的成員里面的i,指向的都是同一個i,不管是循環到第幾次,導致運行時輸出的都是最后一輪的i的值,也就是10。

var a=10
function aaa(a){
alert(a);
}
function bbb(){
var a=20;
aaa();

}
bbb();

//---結果輸出10  執行函數bbb 里面會執行aaa() aaa里面的alert 里的a 尋找作用域,自身有局部變量的話輸出自己,沒有的話去aaa的作用域找 上層的var a=10便是。

function aaa(){

var a=b=10

}

// alert(a) //error 

alert(b)// 10

var a=b=10這種寫法在函數內,b其實是全局變量,a當然是局部變量
執行完aaa(),在全局域里alert(a),當然是undefined,alert(b),就會彈出10

 var a=10

function aaa(){

console.log(a)

var a=20

}

aaa() //undefined 變量提升  這個函數執行時等於

var a=10

function aaa(){

var a;

console.log(a)

var a=20

}

在看一個相似的

 var a=10

function aaa(){

console.log(a)

 a=20

console.log(a)

}

aaa() //10  20

這個吧,就驗證了第二條,雖然是就近原則,但是是就近找var聲明的變量,這個是因為沒有var聲明的變量是全局的,這里只是修改了a的值。所以上面就是因為在函數內沒找到var的a,於是到外面去找了,一找就找到了,於是a就alert出10了;不過沒錯的是a=20后,a確實為20了,只不過alert的時候還沒有執行到那~~

var a=10

function aaa(){

  bbb()

alert(a)

function bbb(){

 var a=20

}

}

aaa()// 10

這是因為在alert(a)的時候,bbb函數中的a確實為20 ,可是它對於這時的alert(a)這句話來說是局部的,alert(a)根本找不到bbb函數中的a,所以在aaa函數中它找不到a,於是乎去外面找,一找,就找到了10。

 

var a=10
function aaa(a){

alert(a);
var a=20

}
aaa(a)

執行過程貌似應該是

var a=10
function aaa(a){
var a;
alert(a);
var a=20
//alert(a);
}
aaa(a)

傳遞進來的10 賦給變量a alert(10) 之后var a=20 覆蓋了之前的10 ,但是函數沒有執行到這里就alert結束了。再后面alert(a) //20

 

傳參時,基本類型傳值,引用類型傳引用。

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];

變量a 將5這個值傳給b  b 和a 沒有關系了。

數組是引用傳遞,把b的指針也指向了 同一個地址,所以b的改變 a也改變

var a = [1,2,3];
var b=a;

b=[1,2,3,4]

alert(a) //[1,2,3]

b 被重新賦值后,指針會從新指向自己的內存地址,脫離a。

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

 var a=10;

function aaa(a){

 a+=3

}

aaa(a)

alert(a) //10

對比:

 var a=10;

function aaa(a){

 a+=3;

alert(a) //13

}

aaa(a)

參數傳遞進去的是值,里面的a是局部變量,不管怎么改都和外面的a 無關。因為不在同一個作用域上。類似:

var a=10
function aaa(a){
alert(a+10)
}
aaa(30) //40
alert(a)//10

var a=[1,2,3]

function aaa(a){

 var a=[1,2,3,4]

}

aaa(a)

alert(a)// [1,2,3]  函數里面的a被重新賦值,和外層的a 不指向同一個a

var a=[1,2,3]

function aaa(a){

a.push(4)

}

aaa(a)

alert(a)// [1,2,3,4]

引用改變添加元素后,指向同一個a,引用傳遞指針,值也變了。

不積跬步無以至千里,不積小流無以成江海


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM