zhuanyongxigua / blog

blog
77 stars 9 forks source link

用浏览器测试几种闭包占用内存的情况 #18

Open zhuanyongxigua opened 6 years ago

zhuanyongxigua commented 6 years ago

我的github https://github.com/zhuanyongxigua/blog

这一篇首先是打算证明一下《三个闭包实例理解闭包对内存的影响》

一共有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是另一种情况),且这个函数所在的执行环境中的变量被这个执行环境中的函数使用。