闭包
人生苦短,不必只做背景板
变量作用域
变量根据作用域的不同分为两种:全局变量和局部变量。
-
函数内部可以使用全局变量。
-
函数外部不可以使用局部变量。
-
当函数执行完毕,本作用域内的局部变量会销毁。
什么是闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数。 ----- JavaScript 高级程序设计
简单理解就是 ,一个作用域可以访问另外一个函数内部的局部变量
// 闭包(closure)指有权访问另一个函数作用域中变量的函数。
//闭包: 我们fn2这个函数作用域访问了另外一个函数fn1里面的局部变量 num
function fn1(){
// num所在的函数则为闭包函数,故fn1 就是闭包函数
var num = 10;
function fn2(){
console.log(num); // 10
}
fn2()
}
fn1();
在 chrome 中调试闭包
-
打开浏览器,按 F12 键启动 chrome 调试工具。
-
设置断点。
-
找到 Scope 选项(Scope 作用域的意思)。
-
当我们重新刷新页面,会进入断点调试,Scope 里面会有两个参数(global 全局作用域、local 局部作用域)。
-
当执行到 fn2() 时,Scope 里面会多一个 Closure 参数 ,这就表明产生了闭包
闭包的作用
提问:我们怎么能在 fn() 函数外面访问 fn() 中的局部变量 num 呢 ?
<script>
function fn() {
var num = 10;
return function {
console.log(num); // 10
}
}
var f = new fn();
f();//外面的作用域能够访问fn函数中的num变量
//打印出num的值,实现闭包
//num一定要等f()函数的执行完毕才会销毁
</script>
闭包作用:延伸变量的作用范围
闭包练习
点击li输出索引号
<ul>
<li>11</li>
<li>22</li>
<li>33</li>
<li>44</li>
</ul>
<script>
//之前我们使用的方法
var lis = document.querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
lis[i].index = i;
lis[i].onclick = function() {
// console.log(i);
console.log(this.index);
}
}
// 闭包方法
var list = document.querySelectorAll('li');
for (var i = 0; i < list.length; i++) {
(function(i) {
//还涉及到同步事件与异步事件,一开始先执行同步事件,
//将立即函数和点击事件绑定,但是里面的i变量没有消失,
//因为立即执行函数没有执行完毕
list[i].onclick = function() {
console.log(i);
//点击第几个li就输出它的下标
}
})(i)
}
</script>
定时器中的闭包
<ul class="nav">
<li>榴莲</li>
<li>臭豆腐</li>
<li>鲱鱼罐头</li>
<li>大猪蹄子</li>
</ul>
<script>
// 闭包应用-3秒钟之后,打印所有li元素的内容
var lis = document.querySelector('.nav').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
(function(i) {
setTimeout(function() {
console.log(lis[i].innerHTML);
}, 3000)
})(i);
}
</script>
闭包思考题
思考题1
有没有发生闭包,返回结果为多少?
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
return function() {
return this.name;
};
}
};
console.log(object.getNameFunc()())
/*解析:
object.getNameFunc()()将其拆解,
代表返回function(){this.name}()立即执行之后的值
function(){this}():立即执行函数,this指向window
var f = object.getNameFunc();
类似于
var f = function() {
return this.name;
}
f();
没有发生闭包,因为没有访问到函数中的变量,打印结果为window*/
思考题2
有没有发生闭包,返回结果为多少?
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
var that = this;
//this指向getNameFunc函数的调用者,object调用,所以that=object
return function() {
return that.name;
//返回的that代表object,所以结果为My Object,
//由于return返回的that是属于
//getNameFunc函数的局部变量,所以有发生闭包
};
}
};
console.log(object.getNameFunc()())
闭包总结
闭包是什么
闭包是一个函数 (一个作用域可以访问另外一个函数的局部变量)
闭包的作用是什么
延伸变量的作用范围