说一下对闭包的理解 ?

闭包:在一个外函数中定义了一个内函数,内函数里使用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成一个闭包。一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。经常用闭包来实现面向对象编程。

function outer() {
     var  a = '变量1'
     var  inner = function () {
            console.info(a)
     }
    return inner    // inner 就是一个闭包函数,因为他能够访问到outer函数的作用域
}

坑点1: 引用的变量可能发生变化

复制代码
function outer() {
      var result = []
      for (var i = 0;i<10;i++){
        result[i] = function () {
            console.info(i)
        }
     }
     return result
}
复制代码
看样子result每个闭包函数对打印对应数字,1,2,3,4,...,10, 实际不是,因为每个闭包函数访问变量i是outer执行环境下的变量i,随着循环的结束,i已经变成10了,所以执行每个闭包函数,结果打印10, 10, ..., 10
怎么解决这个问题呢?
复制代码
function outer() {
      var result = []
      for (var i = 0; i<10;i++){
        result[i] = (function (num) {
             return function() {
                   console.info(num);   // 此时访问的num,是上层函数执行环境的num,数组有10个函数对象,每个对象的执行环境下的number都不一样
             }
        })(i)
     }
     return result
}
复制代码

坑点2: this指向问题

复制代码
var object = {
     name: "object",
     getName: function() {
        return function() {
             console.info(this.name)
        }
    }
}
object.getName()()    // underfined
// 因为里面的闭包函数是在window作用域下执行的,也就是说,this指向windows
复制代码

坑点3:内存泄露问题

复制代码
function  showId() {
    var el = document.getElementById("app")
    el.onclick = function(){
      aler(el.id)   // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
    }
}

// 改成下面
function  showId() {
    var el = document.getElementById("app")
    var id  = el.id
    el.onclick = function(){
      aler(id) 
    }
    el = null    // 主动释放el
}
复制代码

 用闭包解决递归调用问题

复制代码
function  factorial(num) {
   if(num<= 1) {
       return 1
   } else {
      return num * factorial(num-1)
   }
}
var anotherFactorial = factorial
factorial = null
anotherFactorial(4)   // 报错 ,因为最好是return num* arguments.callee(num-1),arguments.callee指向当前执行函数,但是在严格模式下不能使用该属性也会报错,所以借助闭包来实现


// 使用闭包实现递归
function newFactorial = (function f(num){
    if(num<1) {return 1}
    else {
       return num* f(num-1)
    }
}) //这样就没有问题了,实际上起作用的是闭包函数f,而不是外面的函数newFactorial
复制代码

优点:

  1. 不会造成全局变量的污染;
  2. 可以在函数的外部访问到函数内部的局部变量(实现所谓的变量‘公有化’)。
  3. 让这些变量始终保存在内存中,不会随着函数的结束而自动销毁。

缺点:

  1. 闭包导致作用域链的不释放,会造成内存溢出,所以就会占用内存空间
posted @   天青色等烟雨灬  阅读(38)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示