闭包函数
作用域复习
变量根据作用域的不同分为两种:全局变量 局部变量
函数内部可以使用全局变量
函数外部不可以使用局部变量
函数执行完毕,本作用域内的局部变量会销毁
什么是闭包
闭包是有权访问另一个函数作用域中变量的函数,简单理解就是一个作用域可以访问另外一个函数内部的局部变量闭包的作用
在本质上,闭包就是将函数内部和函数外部连接起来的桥梁。
闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。
function fn(){
var num=10;
function fn1(){
console.log(num);//10
}
fn1();
}
fn();
//fn就是一个闭包函数
闭包函数得作用
延伸了变量的作用范围
(1)可以读取父级作用域函数内部的变量;
(2)让变量的值始终保存在内存中(让局部变量变成全局变量),不被垃圾回收机制清除。
function fn() {
var num = 10;
function fun() {
console.log(num);
}
return fun;
}
var f = fn();
f();
// 闭包的作用
// 闭包是有权访问另一个函数作用域中变量的函数**,简单理解就是一个作用域可以访问另外一个函数内部的局部变量
// 我们fn 外面的作用域可以访问fn内部的局部变量
// 作用:延伸了变量的作用范围
function fn() {
var num = 10
function fun() {
console.log(num)
}
return fun
}
var f = fn()
f()
// 类似于
// var f = function(){
// console.log(num)
// }
闭包函数的案例
//1、利用闭包的方式得到当前li 的索引号
for (var i = 0; i < lis.length; i++) {
// 利用for循环创建了4个立即执行函数
// 立即执行函数也成为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i这变量
(function(i) {
lis[i].onclick = function() {
console.log(i);
}
})(i);
//2,3秒后打印所有li元素的内容
<ul class="nav">
<li>1234</li>
<li>4321</li>
<li>5678</li>
<li>8765</li>
</ul>
var lis=document.querySelectAll("li")
for (var i = 0; i < lis.length; i++) {
(function(i) {
setTimeout(function() {
console.log(lis[i].innerHTML);
}, 3000)
})(i);
/*
计算打车价格
起步价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
},
ydPrice:function(flag){
return flag?total+10:total
}
}
})()
// console.log(car)
console.log(car.price(7))
console.log(car.ydPrice(true))
console.log(car.price(1))
console.log(car.ydPrice(false))
闭包函数的缺点
由于闭包会使函数中的变量都保存到内存中,垃圾回收机制不清理,内存消耗很大,所以不能滥用闭包,否则可能导致内存泄漏。
补充:
什么是内存泄漏?
程序的运行都是需要内存的。只要对内存提出要求,操作系统必须供给内存。
当应用程序中的一些代码变量不再需要用到内存时,但是没有被操作系统或者可用内存池回收,就说明它发生了内存泄漏。
即,当已经不再需要某块内存时,这块内存还存在着——内存泄漏
解决闭包引起的内存泄漏的问题:
在退出函数之前,将不使用的局部变量全部删除。
例如:将当前变量的值设置为‘null’,当垃圾回收机制启动时,会自动对这些值为‘null’的变量回收。