看一下阮一峯的還有老馬的。阮一峯的比較明白。
老馬的 :https://www.cnblogs.com/fly_dragon/p/8669057.html
阮一峯說的
下面的代碼如果使用var
,最後輸出的是10
。
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
上面代碼中,變量i
是var
命令聲明的,在全局範圍內都有效,所以全局只有一個變量i
。每一次循環,變量i
的值都會發生改變,而循環內被賦給數組a
的函數內部的console.log(i)
,裏面的i
指向的就是全局的i
。也就是說,所有數組a
的成員裏面的i
,指向的都是同一個i
,導致運行時輸出的是最後一輪的i
的值,也就是 10。
如果使用let
,聲明的變量僅在塊級作用域內有效,最後輸出的是 6。
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
上面代碼中,變量i
是let
聲明的,當前的i
只在本輪循環有效,所以每一次循環的i
其實都是一個新的變量,所以最後輸出的是6
。你可能會問,如果每一輪循環的變量i
都是重新聲明的,那它怎麼知道上一輪循環的值,從而計算出本輪循環的值?這是因爲 JavaScript 引擎內部會記住上一輪循環的值,初始化本輪的變量i
時,就在上一輪循環的基礎上進行計算。
另外,for
循環還有一個特別之處,就是設置循環變量的那部分是一個父作用域,而循環體內部是一個單獨的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
上面代碼正確運行,輸出了 3 次abc
。這表明函數內部的變量i
與循環變量i
不在同一個作用域,有各自單獨的作用域。
但是我自己測試的:只是打印一次abc。這表明函數內部的變量i
與循環變量i
在同一個作用域
for (var i = 0; i < 3; i++) {
var i = 'abc';
console.log(i);
}
//abc
這是爲啥呢呢呢呢呢?
yu哥不知道對否.自己瞎分析一下下;
因爲: let 定義的是塊級作用域。var 定義的變量是函數作用域。
將上面兩個例子改寫一下比較容易理解啊啊啊:
let i;
for ( i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
var i;
for ( i = 0; i < 3; i++) {
var i = 'abc';
console.log(i);
}
//abc
var 這種情況,因爲是函數作用域,所以for循環外面的i 和內部的i是一個作用域,也就是同一個i。所以改變了之後,i第二次循環就是abc了,不小於3,所以只循環一次。
let這種情況,因爲是塊級作用域,所以for循環外面的i 和內部的i不是是一個作用域,for外面的i就是裏面i的父級作用域,從新定義子級裏的i不會影響父級裏面的i。所以會循環三次。
注意。不好理解的時候將變量聲明提出去,這樣好理解。
for(){
}
和
function(){
}
小括號裏面的變量都是可以提出來的。
就像
var obj={
name:"liu",
aa:function(aa){
console.log(aa)
console.log(this)
}
}
obj.aa(this)
//window;
//obj;
function(aa){
}
形參aa就是函數外面的父級作用域裏面的變量。所以結果是window;