鍍金池/ 問答/HTML/ js中非常簡單的變量泄露問題

js中非常簡單的變量泄露問題

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

變量泄露導致上面的a[6]變成10;
我不太理解 這里為什么a[6]是10,我的錯誤思維如下

  1. a[6] 這里沒有變量, 所以內(nèi)存泄露源于循環(huán)
  2. 循環(huán)中,每次都是把當前次數(shù)賦值給對應的數(shù)組,

a[0] = function () { console.log(0);};
a[1] = function () { console.log(1);};
......
a[9] = function () { console.log(9);};
再每一次賦值的時候i的值是正確的,賦值后,每個函數(shù)都是固定輸出一個數(shù)字,也不存在變量
3.請問 我的思維錯在哪里了

回答
編輯回答
有你在

其實 es6 的 let 根本沒抓住問題的本質(zhì)

關(guān)鍵在于 js 作為一個允許副作用的語言,它的 closure 卻只支持引用外層作用域的變量,而不支持「引用」外層作用域中變量的值

C++ 就沒有這個問題~

#include <functional>
#include <iostream>

using namespace std;

int main() {
  function<void()> a[10];
  for (int i = 0; i < 10; i++) {
    a[i] = [i] () {
      cout << i << '\n';
    };
  }
  a[6](); // 6
}

之所以出現(xiàn)這個反直覺的現(xiàn)象,就是因為你那 10 個函數(shù)引用的都是同一個 i 變量,而這個變量的值是 for 循環(huán)最后一次執(zhí)行時的值,也就是 10。

2018年2月12日 15:15
編輯回答
萌小萌

執(zhí)行a[6]()的時候,i已經(jīng)循環(huán)到了10了

2018年6月9日 08:46
編輯回答
咕嚕嚕

簡單的閉包問題,我面試的時候都被問到過好幾次了。

2018年6月10日 20:24
編輯回答
薔薇花

這個題已經(jīng)問爛了也回答不知道多少遍了
i是全局變量 函數(shù)調(diào)用的時候獲取i 此時 i已經(jīng)循環(huán)到了10
下面是個簡單了例子可以理解為經(jīng)歷了兩次循環(huán)

var i = 1;
function a1(){ console.log(i) }

var i = 2;
function a2(){ console.log(i) }

a1();//2
a2();//2

解決方法 將i變?yōu)榫植孔兞?/p>

es6
{
  let i = 1;
  function a1(){ console.log(i) }
}

{
  let i = 2;
  function a2(){ console.log(i) }
}

a1();//1
a2();//2
//es6 let局部變量
for(let i=0;i<10;i++) ...
//or
//自執(zhí)行函數(shù) es5中只有函數(shù)內(nèi)有局部作用域 
for (var i = 0; i < 10; i++) {
  a[i] = (function(i){
      return function () {
            console.log(i);
          };
  })(i)
}
2017年5月16日 23:32
編輯回答
舊螢火

閉包問題,同學你的基礎(chǔ)要加油了.

2018年1月22日 12:10
編輯回答
吃藕丑

問題源于對函數(shù)作用域(鏈)的理解不夠深,一下是個人的一點見解,望能幫助到您:

    var a = [];
    for (var i = 0; i < 10; i++) {   // 此處變量i為全局變量,屬于外層作用域(window)
      // 此處聲明函數(shù),創(chuàng)建函數(shù)的作用域(建立作用域鏈,函數(shù)內(nèi)部能訪問外層作用域中的i變量,但此處只是聲明,并不執(zhí)行)
      a[i] = function () {     
        // 函數(shù)內(nèi)部并未定義i變量,當函數(shù)執(zhí)行時通過聲明函數(shù)時建立的作用域鏈向上查找變量i
        // 調(diào)用a[6]時,for循環(huán)已經(jīng)結(jié)束,變量i已經(jīng)變成10,所以此處打印輸出 10
        console.log(i);   
      };
    }
    a[6](); // 10
2017年10月20日 14:19