JavaScript 闭包
JavaScript 闭包
一、变量
1、JavaScript 变量可以是局部变量或全局变量。
2、函数可以访问是有函数内部定义的变量,函数也可以访问函数外部定义的变量。
3、在web页面中全局变量属于 window 对象。
4、全局变量可应用于页面上的所有脚本。
5、局部变量只能用于定义它函数内部。对于其他的函数或脚本代码是不可用的。
6、全局和局部变量即便名称相同,它们也是两个不同的变量。修改其中一个,不会影响另一个的值。
注意:变量声明是如果不使用 var 关键字,那么它就是一个全局变量,即便它在函数内定义。函数内部声明变量的时候,一定要使用var命令。
二、变量生命周期
1、全局变量的作用域是全局性的,即在整个JavaScript程序中,全局变量处处都在。
2、在函数内部声明的变量,只在函数内部起作用。这些变量是局部变量,作用域是局部性的;函数的参数也是局部性的,只在函数内部起作用。
三、JavaScript 内嵌函数
1、所有函数都能访问全局变量。
2、在 JavaScript 中,所有函数都能访问它们上一层的作用域。
3、JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。
4、内部函数也可以像其他函数一样引用全局变量。
5、只要存在调用内部函数的可能,JavaScript就需要保留被引用的函数。而且JavaScript运行时需要跟踪引用这个内部函数的所有变量,直到最后一个变量废弃,JavaScript的垃圾收集器才能释放相应的内存空间。
四、JavaScript 闭包
闭包是指有权限访问另一个函数作用域的变量的函数。
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
1.1实例
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
add();
add();
add();
// 计数器为 3
1.2实例解析
变量 add 指定了函数自我调用的返回字值。
自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。
add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器。
这个叫作 JavaScript 闭包。它使得函数拥有私有变量变成可能。
计数器受匿名函数的作用域保护,只能通过 add 方法修改。
注意: 闭包是可访问上一层函数作用域里变量的函数,即便上一层函数已经关闭。
2.1实例(一个经典错误)
页面上有若干个div, 我们想给它们绑定一个onclick方法,于是有了下面的代码:
<div id="divTest">
<span>0</span> <span>1</span> <span>2</span> <span>3</span>
</div>
<div id="divTest2">
<span>0</span> <span>1</span> <span>2</span> <span>3</span>
</div>
$(document).ready(function() {
var spans = $("#divTest span");
for (var i = 0; i < spans.length; i++) {
spans[i].onclick = function() {
alert(i);
}
}
});
很简单的功能可是却偏偏出错了,每次alert出的值都是4,简单的修改就好使了
var spans2 = $("#divTest2 span");
$(document).ready(function() {
for (var i = 0; i < spans2.length; i++) {
(function(num) {
spans2[i].onclick = function() {
alert(num);
}
})(i);
}
});
2.2实例解析
for (var i = 0; i < spans.length; i++) { spans[i].onclick = function() { alert(i); } }
上面代码在页面加载后就会执行,当i的值为4的时候,判断条件不成立,for循环执行完毕,但是因为每个span的onclick方法这时候为内部函数,所以i被闭包引用,内存不能被销毁,i的值会一直保持4,直到程序改变它或者所有的onclick函数销毁(主动把函数赋为null或者页面卸载)时才会被回收。这样每次我们点击span的时候,onclick函数会查找i的值(作用域链是引用方式),一查等于4,然后就alert给我们了。而第二种方式是使用了一个立即执行的函数又创建了一层闭包,函数声明放在括号内就变成了表达式,后面再加上括号括号就是调用了,这时候把i当参数传入,函数立即执行,num保存每次i的值。