浅析js中的闭包

闭包

  • this对象
  • 内存泄漏

闭包指那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。

闭包形成的原理作用域链。只要是代码都一个作用域中,写在函数内部的局部作用域,未写在任何函数内部即在全局作用域中;如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域;根据在 [内部函数可以访问外部函数变量] 的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作 作用域链就近原则

闭包带来的问题:由于垃圾回收器不会将闭包中变量销毁,于是就造成了内存泄露,内存泄露积累多了就容易导致内存溢出。

闭包会保留它们包含函数的作用域,所以比其他函数更占用内存。过度使用闭
包可能导致内存过度占用。

一般就是一个函数A,return其内部的函数B,被return出去的B函数能够在外部访问A函数内部的变量,这时候就形成了一个B函数的变量背包,A函数执行结束后这个变量背包也不会被销毁,并且这个变量背包在A函数外部只能通过B函数访问。

this对象

在闭包中使用 this 会让代码变复杂。如果内部函数没有使用箭头函数定义,则 this 对象会在运行时绑定到执行函数的上下文。如果在全局函数中调用,则 this 在非严格模式下等于 window,在严格模式下等于 undefined。如果作为某个对象的方法调用,则 this 等于这个对象。匿名函数在这种情况下不会绑定到某个对象,这就意味着 this 会指向 window,除非在严格模式下 this 是 undefined。不过,由于闭包的写法所致,这个事实有时候没有那么容易看出来。

window.identity = 'The Window'; 
let object = { 
	identity: 'My Object', 
	getIdentityFunc() { 
		return function() { 
			return this.identity; 
		}; 
	} 
}; 
console.log(object.getIdentityFunc()()); // 'The Window'
console.log(object.getIdentityFunc()); // ƒ () { return this.identity; }
window.identity = 'The Window'; 
let object = { 
	identity: 'My Object', 
	getIdentityFunc() { 
		let that = this;
		return function() { 
			return that.identity; 
		}; 
	} 
}; 
console.log(object.getIdentityFunc()()); // 'My Object'
console.log(object.getIdentityFunc()); // ƒ () { return that.identity; }

内存泄漏

在一些旧版本的 IE 中,把 HTML 元素保存在某个闭包的作用域中,就相当于宣布该元素不能被销毁。来看下面的例子:

function assignHandler() { 
	let element = document.getElementById('someElement'); 
	element.onclick = () => console.log(element.id); 
} 

以上代码创建了一个闭包,即 element 元素的事件处理程序。而这个处理程序又创建了一个循环引用。匿名函数引用着 assignHandler()的活动对象,阻止了对element 的引用计数归零。只要这个匿名函数存在,element 的引用计数就至少等于 1。也就是说,内存不会被回收。
只要这个例子稍加修改,就可以避免这种情况,比如:

function assignHandler() { 
	let element = document.getElementById('someElement'); 
	let id = element.id; 
	element.onclick = () => console.log(id);
	element = null; 
} 

修改后,闭包改为引用一个保存着 element.id 的变量 id,从而消除了循环引用。
不过,光有这一步还不足以解决内存问题。因为闭包还是会引用包含函数的活动对象,而其中包含element。即使闭包没有直接引用 element,包含函数的活动对象上还是保存着对它的引用。因此,必须再把 element 设置为 null。这样就解除了对这个 COM 对象的引用,其引用计数也会减少,从而确保其内存可以在适当的时候被回收。

你可能感兴趣的:(前端知识汇总,javascript,前端,开发语言)