用瀏覽器測試幾種閉包占用記憶體的情況
@(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是另一種情況),且這個函式所在的執行環境中的變數被這個執行環境中的函式使用。