1、作用域和作用域链
-
作用域 变量和函数的可使用范围叫做作用域。作用域可以认为它是一个封闭的空间,只允许在这个封闭的空间内进行一些操作,也将这个封闭空间称为私有作用域。
-
作用域链 每个函数都会有一个作用域,查找变量或函数时,由局部作用域到全局作用域依次查找,这些作用域的集合就称为作用域链。
-
函数作用域 函数执行时,就会在内存中创建一个私有作用域——封闭的空间。正常情况下,函数执行完成后,这个私有作用域(封闭的空间)就会销毁,但闭包不会被销毁。
-
内存回收机制 系统自动会清理回收不到的内存。
-
内存泄露 不再用到的内存,没有及时释放,就叫做内存泄漏。
-
导致内存泄露原因: 内存泄漏是指我们已经无法再通过js代码来引用到某个对象,但垃圾回收器却认为这个对象还在被引 用,因此在回收的时候不会释放它,导致了分配的这块内存永远也无法被释放出来。如果这样的情况越 来越多,会导致内存不够用而系统崩溃。
2、闭包
2.1、闭包的含义
函数执行,形成一个私有的执行上下文,保护里边的私有变量不受外界的干扰,除了保护私有变量外, 还可以保存一些内容,这样的模式叫做闭包。
总之,在一个函数A内定义一个函数B,这个函数B一直保持有对外部函数A中作用域的访问权限,即B函数一直拥有访问A函数内变量的权限。
2.2、闭包的作用
1、保护:用来保护一些私有变量不被污染; 将私有变量放在一个私有的作用域中,防止相互之间的变量命名冲突;
2、保存:用来保存私有的变量;如循环绑定事件引发的索引问题
2.3、闭包的应用
循环绑定事件索引问题
var btnBox = document.getElementById('btnBox'),
inputs = btnBox.getElementsByTagName('input')
var len = inputs.length;
for(var i = 0; i < 1en; i++){
inputs[i].onclick = function () {
alert(i) //循环输出len的值
}
}
- 1、使用闭包解决
var btnBox = document.getElementById('btnBox'),
inputs = btnBox.getElementsByTagName('input')
var len = inputs.length;
for(var i = 0;i<len;i++){
(function(i){
inputs[i].onclick = function () {
alert(i)
}
})(i)
}
- 2、使用自定义属性
var btnBox = document.getElementById('btnBox'),
inputs = btnBox.getElementsByTagName('input')
var len = inputs.length;
for(var i = 0;i<len;i++){
inputs[i].index=i
inputs[i].onclick = function () {
alert(this.index)
}
}
- 3、ES6
var btnBox = document.getElementById('btnBox'),
inputs = btnBox.getElementsByTagName('input')
var len = inputs.length;
for(let i = 0;i<len;i++){
inputs[i].onclick = function () {
alert(i)
}
}
2.4、闭包的优缺点
- 优点:通过创建私有作用域(闭包),用来保存私有变量;
- 缺点:生成多个不销毁的私有作用域(堆内存),影响性能;