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都是不同且獨立的
上面代碼中,變量i
是var
命令聲明的,在全局范圍內都有效,所以全局只有一個變量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,引用傳遞指針,值也變了。