LeoWangJ / blog

紀錄學習文章
1 stars 0 forks source link

函數與閉包 #18

Open LeoWangJ opened 4 years ago

LeoWangJ commented 4 years ago

函數的返回值的影響因素有兩個:

let a = 1
function add(x){
   return x + a
}
{
   let a = 2
   add(2)  // 是 3 or 4 ?
}

此時add(2)函式的2就是我們傳入的參數,return 的 a 就是由我們在環境中所定義的變數。

那麼答案是多少呢?

我們說影響的因素有兩個,其中有一個是"定義時"的環境env。
這個"定義時"指的是函數在定義時的地方,那麼跟我們函數在相同環境的a為1, 所以答案是3。
假如我們把add函數移至a=2 的區塊環境內,則答案為4。

其實在函數外面我們能夠訪問函數外面的變數,就是我們常見的閉包

閉包就是該函數與在函數外面被訪問的變數

那閉包有什麼用呢? 他能夠幫我們儲存環境變數的值,使得能夠重複使用該參數。

先看一個經典的題目:


for(var i = 0; i < 6; i++){
   setTimeout(()=>console.log(i))
}

答案是什麼?

有一定經驗的前端一定知道setTimeout是非同步的,等到印出console.log(i)時i 已經都增加到6了,而且setTimeout六個函式中的i 都是共用相同的環境變數i,所以此時答案就是6個6。

那要怎麼正常打印出012345呢?

可以使用立即執行函數或者ES6的let。

for(let i = 0; i < 6; i++){
   setTimeout(()=>console.log(i))
}

由於let是區域環境也就是在{ }那就是一個環境,所以我們所宣告的i會在該環境下保持住當前i的值,所以當setTimeout的函數執行時能夠取得到i = 0,1,2,3,4,5的值。