1 函数的定义和调用
1.1函数的定义方式
1.函数声明方式function关键字(命名函数)
2 this
3 严格模式
4 高阶函数
5 闭包
5.1 变量作用域
变量根据作用域的不同分为两种∶全局变量和局部变量。
1.函数内部可以使用全局变量。
2.函数外部不可以使用局部变量。
3.当函数执行完毕,本作用域内的局部变量会销毁。
5.2 什么是闭包
闭包( closure )指有权访问另一个函数作用域中变量的函数。----- JavaScript高级程序设计
简单理解就是,一个作用域可以访问另外一个函数内部的局部变量。
<script>
// 闭包(closure)指有权访问另一个函数作用域中变量的函数
function fn() {
var num = 10;
// fun()函数中可以访问fn函数作用域中的局部变量的num
function fun() {
console.log(num);// 10
}
fun();
}
fn();
</script>
利用Chrome浏览器查看有没有闭包的产生。点开“Sources”,在语句fn();
上打断点后刷新页面。
运行到fn();
时,fn()还没有被调用,是在最外层,是全局作用域Window
点击F11,执行下一步。进入局部作用域 – fn的作用域内。在fn的局部作用域里,有fun函数、num变量和this。
执行下一步,直到进入fun函数的作用域内(如下图)。Scope里面多了一个参数-- closure,里面有个num变量。
意思是:fn是一个闭包(待确认,感觉与解释不对应。老师确实说的是,被访问的变量所在的函数是闭包函数)。可以访问fn函数作用域里的num这个变量。
5.3 闭包的作用
闭包的主要作用:延伸了变量的作用范围。
△ num变量不会等函数执行完毕就销毁,只有等所有的函数都执行完了才销毁。
△ fn外面的作用域可以访问fn内部的局部变量。
便于理解的写法:
<script>
// 使 fn外面的作用域可以访问fn内部的局部变量
function fn() {
var num = 10;
// fun()函数可以访问fn函数作用域中的局部变量的num
function fun() {
console.log(num);// 10
}
return fun;
}
var f = fn(); // 调用fn():对num进行赋值,并且返回fun,f存储fun()
// 类似于
// var f = function fun() {
// console.log(num);
// }
// f函数一调用就会执行fun函数,因为存的是fun()。
// fun()函数本身在fn函数中,故可以访问fn函数中的变量。
f();
</script>
简易写法 – 将fun函数,写成匿名函数:
<script>
// 使 fn外面的作用域可以访问fn内部的局部变量
function fn() {
var num = 10;
// 简易写法:
return function() {
console.log(num);// 10
}
}
var f = fn(); // 调用fn(),对num进行复制,并且返回fun,f存储fun()
// f函数一调用就会执行fun函数,因为存的是fun()。
// fun()函数本身在fn函数中,故可以访问fn函数中的变量。
f();
</script>
5.4 闭包的应用
应用1:点击li输出对应的索引号
<ul class="nav">
<li>草莓</li>
<li>芒果</li>
<li>香蕉</li>
<li>火龙果</li>
</ul>
<script>
// 1.之前的做法:利用动态添加属性的方式
var lis = document.querySelector('.nav').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
lis[i].index = i;
lis[i].onclick = function () {
console.log(this.index);
}
}
// 2.利用闭包循环注册点击事件
var lis = document.querySelector('.nav').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
// 利用for循环创建4个立即执行函数
// 每次循环都会创建一个立即执行函数
(function(i) {
lis[i].onclick = function () {
console.log(i);
}
})(i);
}
</script>
应用2:循环中的setTimeout()
// 2.利用闭包得到li的索引值
var lis = document.querySelector('.nav').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
// 利用for循环创建4个立即执行函数
// 每次循环都会创建一个立即执行函数
(function(i) {
setTimeout(() => {
// console.log(i);
console.log(lis[i].innerText);
}, 3000)
})(i)
}
应用3:计算打车价格
<script>
//闭包应用-计算打车价格
//打车起步价13(3公里内),之后每多一公里增加5块钱.用户输入公里数就可以计算打车价格
//如果有拥堵情况,总价格多收取10块钱拥堵费
var car = (function() {
var start = 13;
var total = 0;
return {
price: function(n) {
if (n <= 3) {
total = start;
} else {
total = start + (n - 3) * 5;
}
return total;
},
yd: function(flag) {
return flag ? total + 10 : total;
}
}
})();
console.log(car.price(5));//23 = 13 + 5 * 2
console.log(car.yd(true));//33 = total + 10
console.log(car.price(1));//13
console.log(car.yd(false));// total
</script>
https://www.bilibili.com/video/BV1Ki4y1T7RF?p=69 待补