用瀏覽器測試幾種閉包占用記憶體的情況

磚用冰西瓜發表於2018-06-21

用瀏覽器測試幾種閉包占用記憶體的情況

@(markdown及附件筆記)[真傳] 我的github github.com/zhuanyongxi…

這一篇首先是打算證明一下《三個閉包例項理解閉包對記憶體的影響》

一共有10個例子,例7、8、9需要注意

只測試了Chrome,Chrome版本為67.0.3396.87(正式版本) (64 位)

例1

var a = 12;
function fn() {
  var a = new Array(10000000).join('x');
  return function () {
    var b = 1 + a;
  }
}
var f = fn();
複製程式碼

結果,佔用記憶體。

圖一

圖一

例2

var oDiv = document.getElementById("div1");
~function() {
  var fn = function() {};
  fn.data = new Array(10000000).join('x');
  oDiv.onclick = fn;
}();
複製程式碼

結果同上圖。如果把例子改成:

var oDiv = document.getElementById("div1");
~function() {
  var fn = function() {};
  fn.data = new Array(10000000).join('x');
  // oDiv.onclick = fn;
}();
複製程式碼

結果就是這樣了,區域性作用域中的函式fn被銷燬了。

圖二

圖二

例3

function fn(){
  var a = new Array(10000000).join('x');
  return function(){
    var b = 1 + a;
  }
}
fn();
複製程式碼

結果同圖二,返回函式沒有被全域性變數接住。

例4

這是一個延時銷燬的例子。

function fn(){
  var a = new Array(10000000).join('x');
  return function(){
    var b = 1 + a;
  }
}
fn()();
複製程式碼

先這樣卡主斷點:

用瀏覽器測試幾種閉包占用記憶體的情況

測試記憶體結果同圖一。

然後讓程式執行完成,測試記憶體的結果就變成了圖二。

例5

var fn;
function foo() {
  var a = new Array(10000000).join('x');
  function baz() {
    var b = 1 + a;
  }
  fn = baz;
}

foo();
複製程式碼

結果同圖一。

例6

function fn() {
  var a = new Array(10000000).join('x')
  return function () {
    console.log("test");
  }
}
var f = fn();
複製程式碼

結果同圖二,沒有被返回的函式使用,銷燬。

例7

function fn() {
  var a = new Array(10000000).join('x')
  var b = new Array(10000000).join('x')
  return function () {
    var b = 1 + a;
  }
}
var f = fn();
複製程式碼

結果同圖一,被返回的函式使用的變數被儲存了,沒有被使用的被銷燬了。

例8

function fn() {
  var a = new Array(10000000).join('x');
  
  function another() {
    var b = 1 + a;
  }
  
  return function() {
    console.log("test");
  };
}
var f = fn();
複製程式碼

結果同圖一,變數沒有被除返回函式之外的其他函式使用,依然會有記憶體被佔用。

例9

function fn() {
  var a = new Array(10000000).join('x');
  return function(a) {
    var b = 1 + a;
  }
}

var f = fn();
複製程式碼

結果同圖二,沒有被佔用,變數a實際上被重新宣告瞭。

例10

(function(a) {
  setTimeout(function() {
    var b = 1 + a;
  }, 0);
})(new Array(10000000).join('x'));
複製程式碼

結果同圖一,記憶體被佔用。 這種會被拿來當做面試題:

for(var i = 1; i < 10; i++) {
  (function(i) {
    setTimeout(function() {
      console.log(i);
    }, 0);
  })(i);
}
複製程式碼

總結

閉包環境中的變數會有儲存在記憶體中的條件:返回了一個函式被使用(通常是被賦值給了一個外部的變數,例4和例10是另一種情況),且這個函式所在的執行環境中的變數被這個執行環境中的函式使用。

相關文章