JavaScript 闭包是怎样经由历程作用域链霸占更多内存的?
本文是作者进修《JavaScript 高等程序设计》7.2第一小节的一点个人明白,细致教程请参考原课本。
在弄清楚这个题目之前,我们有必要搞清楚下面这几个题目:
起首,什么是闭包?
定义:闭包 是指 有权接见另一个函数作用域中变量的函数。
怎样建立闭包?
在一个函数内部建立另一个函数,是建立闭包最常见的体式格局。
一个平常的函数实行的时刻都发生了什么?
建立一个实行环境,内里有这个函数的变量对象,保留了函数可接见的一切数据。
建立了作用域链,用来保证可接见变量的有序接见。
函数实行历程建立了一个函数的运动对象,作用域链的最前端指向这个对象。
函数读取写入值,在作用域链内里查找。
函数实行终了返回值后:实行环境、作用域链和运动对象一并烧毁。
明白了这些以后,考核下原书的代码:
function createCompare(property){
return function(obj1,obj2){
var value1=obj1.property;
var value2=obj2.property;
if (value2 < value1){
return 1;
} else if (value2 >value1){
return 1;
} else {
return 0;
}
};
}
var compareNames = createCompare("name");
var result = compareNames({name : "mars1"},{name : "mars2"});
个中,createCompare 函数返回了一个匿名函数,这个匿名函数就是一个闭包。它援用了createCompare函数的参数变量property。
建立compareNames 变量的时刻,就建立了createCompare函数的运动变量:个中property = name etc. 同时返回了匿名函数给compareNames变量,它也有本身的实行环境与作用域链,作用域链援用了建立的compareNames运动对象。
result 定义历程,建立了compareNames的运动对象,个中obj1 = {name : “mars1”} etc.
如许,为result 赋值的compareNames函数实行环境的作用域链以下:
compareNames运动对象 → createCompare运动对象 → 全局对象。
那末题目来了,这个闭包是怎样致使占用更多内存的?
函数实行终了,compareNames 变量并未消逝,不会被渣滓接纳,而它指向的闭包(匿名函数)的作用域链援用着createCompare 函数的运动变量。所以createCompare函数虽然实行终了返回了匿名函数,然则它的运动对象并不会和实行环境、作用域链一样被烧毁,由于另有compareNames的作用域链在援用。如许就相当于闭包照顾了包括它的函数运动对象。
因而要开释compareNames照顾的作用域,必需手动消除援用:
var compareNames = null;