標籤:分配 get 運用 find 兩種 很多 使用 http ber
因為js是一門動態語言,動態分配記憶體的方式讓使用者運用快速便捷,卻忽略了他的記憶體配置機制,今天我來試著理清思路。
還是那個慣例,從基礎講起,然後發散思維,由淺入深。
JavaScript有兩種變數類型,原始值和引用值。原始值指的是未經處理資料類型,分別為undefined,null,number,string,boolean類型。引用值指的是複合資料類
型,即Object、Function、Array。
原始值和引用值儲存在記憶體的位置分別為棧和堆。原始值是儲存在棧中的簡單資料區段,它們的值儲存在變數訪問的位置。引用值是儲存在堆中的對象(儲存在棧
中的只是一個指標,指向儲存在堆中的實際對象)。
基礎都很簡單,但是要活用,然後我們看一個閉包的例子:
for(var i=0,arr=[];i<=3;i++) { arr.push(function(){ alert(i); }); } arr[0](); // 4 arr[1](); // 4
關於這個經典閉包的例子,看了很多的解釋,但我認為還是從記憶體的角度來解析最好,我們來活學活用。
(1)預解析,i,arr,匿名函數
(2)從上而下解析,i=0,arr[0]=匿名函數
(3)i=1,arr[1]=匿名函數
(4)i=2,arr[2]=匿名函數
(5)i=3,arr[3]=匿名函數
(6)i=4,迴圈結束
(7)執行arr[0],因為存入arr內的匿名函數其實是個指標,所以現在才開始執行匿名函數,此時i為4
(8)同理,arr[1]==arr[2]==arr[3]==4
其實在(1)時,i為undefind,而arr數組和匿名函數都是個指標,後續慢慢為arr數組開闢了記憶體空間,裡面存入了匿名函數的指標
既然你都知道了原理抓住了命門,那怎麼解決是不是很簡單了。
所以解決閉包問題,我們有很多思路,可以讓匿名函數即刻執行儲存結果,也可以把當前迴圈時i的值儲存在函數裡等等。
這裡隨便列幾個供參考,思路可能還有很多
(1)
for(var i=0,arr=[];i<=3;i++) { arr.push(function(i){ alert(i); })(i); }
這是讓匿名函數即刻執行儲存結果,注意這幾個i的含義,傳入參數i與變數i
(2)
for(var i=0,arr=[];i<=3;i++) { let a = i; arr.push(function(){ alert(a); }); }
這是把當前迴圈時i的值儲存,let是ES6新文法
談一談js的記憶體配置