標籤:記憶體 length 面試 logs 點擊 好的 面試題 解決 xxx
JavaScript中的函數執行會形成私人的範圍。
(1)範圍的銷毀
一般情況下,函數執行形成一個私人的範圍,當執行完成後就銷毀了->節省記憶體空間
(2)範圍的不立即銷毀
function fn(){ var i=10; return function(n){ console.log(n+i++); }}fn()(15);//->先執行fn,有一個私人的變數i=10,返回一個堆記憶體位址 xxxfff111,我們發現這個地址還用到了一次,那麼當前的這個fn形成的私人範圍(A)就不能立即銷毀了,
xxxfff111(15)->輸出25,A中的i變為11;當xxxfff111執行完了,發現這個地址沒用了,瀏覽器就把A、xxxfff111都釋放了fn()(20);//->在執行fn的時候一切都從新開始了,和上面的步驟是一樣的->輸出30
(3)範圍的立即銷毀
function fn(){ var i=10; return function(n){ console.log(n+i++); }}var f=fn();//->fn執行形成一個私人的範圍A,A中有一個私人的變數i=10,A中返回一個地址xxxfff11,被外面的f佔用了,那麼當前的A就不能銷毀了f(15);//->輸出25,讓A中的i=11f(20);//->輸出31,讓A中的i=12
面試題:
// 關於記憶體釋放的面試題function fn() { var i = 10; return function (n) { console.log(n + (++i)); }} var f = fn(); //首先把fn執行,然後把執行的結果賦值給f,函數執行只要看函數裡面有沒有return f(15); //26 //引用,執行完不會立即釋放 f(20); //32 fn()(15); //26 //每次執行完記憶體釋放,範圍銷毀 fn()(15); //26 fn()(20); //31 fn()(30); //41 f(30); //43
幾種不銷毀常用到的形式:
(1)函數執行,返回一個引用資料類型的值,並且在函數的外面被別人接收了,那麼當前函數形成的私人範圍就不在銷毀了-->例如上面的案例 var f=fn();
(2)在函數執行的時候,裡面的一個小函數的地址賦值給了外面元素的點擊事件,那麼當前小函數也相當於被外面佔用了,大函數執行形成的私人的範圍也不能銷毀了
//每一次迴圈都執行自執行函數形成一個私人的範圍(迴圈三次就有三個範圍,每一個範圍中都有一個i,第一個儲存的是0,第二個存數的是1..),在每一個私人的範圍中都把裡面的函數綁定給了外面元素的點擊事件,這樣的話每一次形成的範圍都不銷毀了(三個不銷毀的範圍)var oLis=document.getElementsByTagName("li");for(var i=0;i<oLis.length;i++){ (function(i){ oLis[i].onclick=function(){ tabChange(i); } })(i);}
(3)在使用setTimeout實現輪詢動畫的時候,我們如果move需要傳遞參數值,那麼像下面這樣的寫法會行成很多的不銷毀的範圍,非常的耗效能
function move(tar){ <js code> //window.setTimeout(move,10); ->第二次執行move的時候我們沒有給它傳值(這樣寫不行) window.setTimeout(function(){ move(tar); },10);//->這樣寫實現了,但是每一次執行定時器都會形成一個私人的所用域(匿名函數形成的)A,在A中使用了上級範圍中的tar的值,而且執行了move又形成了一個小的範圍(而在小的範圍中會使用tar的值),這樣每一次定時器形成的A都不能銷毀了}move(100);//->第一次這樣執行傳遞100//解決方案function move(tar){ (function _move(){ <js code> window.setTimeout(_move,10); })();}move(100);//->第一次這樣執行傳遞100
JS中記憶體空間釋放的問題(堆記憶體、棧記憶體)
[Google瀏覽器]
我們開闢一個記憶體,可能或有一些其他的變數等佔用了這個記憶體,Google瀏覽器都會間隔一段時間看這個記憶體還有沒有被佔用,如果發現有沒有被佔用的記憶體了,就自己幫我們回收了(記憶體釋放)
[Firefox和IE]
我們開個記憶體,當我們引用了它,就在記憶體中記錄一個數,增加一個引用瀏覽器就把這個數+1,減少一個引用,瀏覽器就把這個數-1...當減到零的時候瀏覽器就把這個記憶體釋放了;但是有些情況下(尤其是IE)記著記著就弄亂了,記憶體就不能釋放了-->瀏覽器的記憶體泄露
var obj={};
我們養成一個好的習慣,當我們obj這個對象使用完成了,我們手動的obj=null (nullNull 物件指標),瀏覽器會自己把剛才的堆記憶體釋放掉
參考:關於JS中範圍的銷毀和不銷毀的情況總結
js範圍的銷毀、不立即銷毀、不銷毀