JavaScript-JS闭包的理解

闭包

1.定义

本质:在一个函数内部创建另一个函数。

只要存在函数嵌套,并且内部函数调用了外部函数的属性,就产生了闭包!!

闭包的特性:

  • 函数嵌套函数
  • 函数内部引用函数外部的参数和变量
  • 参数和变量不会被垃圾回收机制回收

闭包的优点:

  • 保护函数内的变量安全,实现封装,防止变量流入其他环境发生命名冲突
  • 在内存中维持一个变量,延长变量的生命周期
  • 匿名自执行函数可以减少内存消耗

闭包的缺点

  • 被引用的私有变量不能被销毁,增大了内存的消耗,造成内存泄露,解决办法是可以在使用完变量后手动将其赋值为null
  • 其次由于闭包涉及跨域访问,所以会导致性能损失,我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响

闭包的作用:

  • 使用函数内部的变量在函数执行完之后,仍然存活在变量中(演唱了局部变量的生命周期)
  • 让函数外部可以操作(读写)到函数内部的数据

2.实例

1.函数作为返回值

function a(){
    var name ='tom'
    return function(){
        return name
    }
}
var b = a()
console.log(b())//name

定义一个函数a,并以另外一个函数作为a函数的返回值,内部函数又使用了a中的属性name,那么这个时候就产生了闭包.我们定义一个变量b接收a的返回值,此时b指向a中嵌套的函数,并且可以使用a中的属性name,故执行b时,会返回name的值为‘tom’

function fn(){
    var num = 3
    return function(){
        var n = 0
        console.log(++n)
        console.log(++num)
    }
}
var fn1=fn()
fn1()// 1 4
fn1()// 1 5

fn中定义内部函数,产生了闭包,内部函数引用的外部i变量时num,于是当定义fn1接收fn的返回值时num会存在于内存中直到fn1销毁,所以每次执行fn1,num都是内存中已经存在的值,故而num可以累加,而n是内部函数中定义的临时变量,当执行完函数后立马销毁,不会存在于内存中,故而每次调用函数不会累加


我们来看一个体现闭包作用的示例

for (var i = 0; i <5; i++) {
	   setTimeout(function(){
          console.log(i);
         },100) 
 }

当我们执行这段代码时,控制台不会依次打印0 1 2 3 4而是打印数 5 5 5 5 5,为什么?

因为我们在循环中设置了延时函数setTimeOut,原来由于js是单线程的,所以在执行for循环的时候定时器setTimeout被安排到任务队列中排队等待执行,而在等待过程中for循环就已经在执行,等到setTimeout可以执行的时候,for循环已经结束,i的值也已经编程5,所以打印出来五个5

怎么在不使用es6中新特性let的情况下,让其正常输出 0 1 2 3 4?答案是闭包

for (var i = 0; i <5; i++) {
    (function(i){
        setTimeout(function(){
            console.log(i);
        },100)
    })(i)
}

在for循环中我们使用一个立即执行函数,并在其中嵌套延时函数,眼熟函数中使用了外部函数的属性,这个时候就产生了嵌套,引用的i被存在内存中没有销毁.

整个循环过程就是 ,每一次循环都立即执行函数,并将i值存储在内存中,在循环完成之后,延时函数开始执行,依次输出0 1 2 3 4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值