鍍金池/ 問答/HTML/ js 循環(huán) i 值問題

js 循環(huán) i 值問題

var Greeters = []
for (var i = 0 ; i < 10 ; i++) {
Greeters.push(function () { return console.log(i) })
}
Greeters[0]() // 10
Greeters[1]() // 10
Greeters[2]() // 10

var Greeters = []
for (var i = 0 ; i < 10 ; i++) {
Greeters.push(i)
}
Greeters[0] // 0
Greeters[1] // 1
Greeters[2] // 2
看了for循環(huán)問題和函數(shù)形參問題 這個提問 自己試了下,還不是很懂,
為什么第一段代碼 是 10 10 10 第二段代碼又變成了 0 1 2
求大佬 通俗點的解釋,打個比方 舉個栗子.

回答
編輯回答
冷眸
  1. 房子里有一個i和10個小盒子,隨著i的變大,往10個小盒子里都塞了一個function () {console.log(i)}的函數(shù),那么執(zhí)行的時候就會去找i,可是你又沒有把i的值傳進函數(shù),函數(shù)內里找不到i的值,所以會去外面房子里找,這個時候i已經是10了。
  2. 房子里有一個i和10個小盒子,隨著i的變大,你把i當時的值直接塞進了小盒子里。
  3. let的則是,房子里有10個屋子,你在屋子里聲明了一個變大的i,然后又將function () {console.log(i)}塞到了一個小盒子里,執(zhí)行的時候去找i,函數(shù)里沒i的值,會在屋子里找到各自的i,所以分別是0-9。

總結下就是:

  1. 房子跟屋子都是作用域。小盒子對應你Greeters數(shù)組的每一項。作用域鏈是函數(shù)->(屋子)->房子。
  2. 函數(shù)中變量的值是在執(zhí)行時確定的,作用域鏈是在聲明時確定的,會沿著作用域從內往外找。
  3. let會形成一個作用域。

改了答案,剛發(fā)現(xiàn)寫著寫著把小盒子的設定弄錯了。

2018年1月8日 10:27
編輯回答
若相惜

1.

var Greeters = []
for (var i = 0 ; i < 10 ; i++) {
Greeters.push(function () { return console.log(i) })
}
Greeters[0]() // 10
Greeters[1]() // 10
Greeters[2]() // 10

其中var i = 0定義了變量i值為0,假設其地址是addr0。在for的過程中i的值不斷從0~9變化,每變化一次他的存儲地址跟著變化一次,完成了整個for的過程i指向addr9,最后var i = 10,判斷超出i<10,不執(zhí)行for,此時i最終指向addr10,這個時候不管怎么引用函數(shù),i的存儲地址都是addr10其值為10。
2

var Greeters = []
for (var i = 0 ; i < 10 ; i++) {
Greeters.push(i)
}
Greeters[0] // 0
Greeters[1] // 1
Greeters[2] // 2

這里推向Greeters的不是變量,而是確切的數(shù)字,所以其指向地址不改變其值不改變。

2018年6月8日 05:20
編輯回答
久不遇

你有10個蘋果往箱子里裝,裝之前你需要寫上現(xiàn)在是第幾個,寫字其實就相當與一個方法,然后放箱子里.
區(qū)別就是第一個你放進箱子里的是一個寫字的方法(function () { return console.log(i) }) 你并沒有寫,因為他沒執(zhí)行.
等你十個都放進去了之后,你拿出來一個要寫字了(就是要執(zhí)行這個方法了),但是現(xiàn)在已經十個都放進去了,已經操作到第十個了,現(xiàn)在就是第10個,你拿哪個出來寫個字不都是10么.

第二種就是你先寫了字,在放進去.

2018年5月7日 02:24
編輯回答
我甘愿

又是可愛的我。
舉例子不會,但是我可以告訴你要想清楚哪些問題。
其次,這個問題的主要是三點,一個是let和var的區(qū)別,第二是for循環(huán)的問題,第三是涉及到了函數(shù)形參與實參的問題。
先說第一個問題,let和var都是用來聲明局部變量,既然叫局部變量,想必你也知道,在當前代碼塊結束之后,這個變量就不能用了。但是不能用是不能用了,let聲明的變量系統(tǒng)就直接把變量地址和值都回收了(就像刪了,放進回收站了),但是var聲明的變量系統(tǒng)還保留了它的地址和值。
第二個問題,注意到for循環(huán)中function的問題,要想清楚function()這個操作是沒有做值的傳遞,換句話說,里面的變量是調用外層的變量值(相當于對于該函數(shù)的全局變量)。
第三個問題重中之重,函數(shù)調用時,引入函數(shù)主體中的形參實際上是你放入()中的實參的一個復制。

2018年7月23日 08:33
編輯回答
伐木累

看錯了重新答
我看了鏈接 鏈接的問題是變量作用域問題
js中只有函數(shù)內有局部作用域
鏈接的第二個循環(huán)是let這是es6新的聲明局部變量
第一種調用Greeters[0]的時候是10是因為調用的時候才從全局取值 這時候i已經循環(huán)完畢保持為10
第二種調用Greeters[0]的時候是0是因為調用的時候是先從局部作用域取值所有i為0


你的第二個是直接把值0放進數(shù)組里調用的時候直接取值0

2018年8月9日 01:41
編輯回答
話寡

第一個 并不是push了 1 23 這些數(shù)字 而是push了一個函數(shù)對象
他push了是9個相同的 函數(shù) 你每次是需要調用 函數(shù) 通過數(shù)組索引訪問到函數(shù) 然后調用函數(shù)
也就是小括號作用 所以每次都是輸出10
每次調用for 循環(huán)是瞬間執(zhí)行完的 所以他只會輸出 10

第二次是把1 2 3 4這些數(shù)字push 到數(shù)組里面 所以 你按索引訪問就是對應的每個數(shù)字

2017年1月18日 09:44
編輯回答
兔囡囡

第一種是往Greeters push 了一個函數(shù),而for循環(huán)中的i是用var聲明的,var聲明變量沒有塊級作用域,這里的i相當于全局變量,當調用函數(shù)的時候for循環(huán)里的i已經變成了10,所以打印的都是10

2018年2月13日 14:37