zoukankan      html  css  js  c++  java
  • JavaScript高级__深入了解闭包

    理解闭包

    1.如何产生闭包

    当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包

    2.闭包到底是什么

    闭包是嵌套的内部函数

    包含被引用变量(函数)的对象

    注意:闭包存在于嵌套的内部函数中

    3.产生闭包的条件

    函数嵌套

    内部函数引用了外部函数的数据(变量/函数)

    function fn1() {
      // 此时闭包就已经产生了(函数提升,内部函数对象已经创建了)
      var a =2
      function fn2() {
        a++
        console.log(a)
      }
      return fn2
    }
    var f = fn1()
    f() // 3
    f() // 4
    f = null // 闭包死亡(包含闭包的函数对象成为垃圾对象)

    常见的闭包

    1.将函数作为另一个函数的返回值

    2.将函数作为实参传递给另一个函数调用

    闭包的作用

    1.延长局部变量的生命周期

    2.从外部可以(间接)操作函数内部的局部变量

    闭包的生命周期

    1.产生:在嵌套内部函数定义执行完成就产生了(不是在调用时)

    2.死亡:在嵌套内部函数成为垃圾对象时

    闭包的应用

    自定义JS模块

    *具有特定功能得js文件

    *将所有的数据和功能都封装在一个函数内部(私有的)

    *只向外暴露一个包含n个方法的对象或函数

    *模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能

    案例一

    function myModule() {
      // 私有变量
      var msg = 'Hello World'
      // 操作私有变量的函数
      function upperCase() {
        console.log('upperCase()' + msg.toUpperCase())
      }
      function lowerCase() {
        console.log('lowerCase()' + msg.toLowerCase())
      }
      // 向外部暴露对象(给外部使用的方法)
      return {
        upperCase: upperCase,
        lowerCase: lowerCase
      }
    }

    案例二

    (function () {
      // 私有变量
      var msg = 'Hello World'
      // 操作私有变量的函数
      function upperCase() {
        console.log('upperCase()' + msg.toUpperCase())
      }
      function lowerCase() {
        console.log('lowerCase()' + msg.toLowerCase())
      }
      // 直接挂在window上
      window.myModule = {
        upperCase: upperCase,
        lowerCase: lowerCase
      }
    })()

    闭包的缺点以及解决

    1.缺点

      *函数执行完后,函数内的局部变量没有释放,占用内存时间变长

      *容易造成内存泄漏

    2.解决

      *能不用闭包就不用

      *及时释放 (赋值null)

    闭包代码案例

    代码一

    var name = "window"
    var obj = {
      name : 'object',
      getName : function() {
        return function() {
          return this.name;
        }
      }
    }
    console.log(obj.getName()()) // window

    代码二

    var name = "window"
    var obj = {
      name : 'object',
      getName : function() {
        var that = this
        return function() {
          return that.name
        }
      }
    }
    console.log(obj.getName()()) // object

    代码三

    function fun(n, o) {
      console.log(o)
      return {
        fun: function(m) {
          return fun(m, n)
        }
      }
    }
    var aa = fun(0); // undefined
    aa.fun(1); // 0
    aa.fun(2); // 0
    aa.fun(3); // 0
    
    var bb = fun(0).fun(1).fun(2).fun(3); // undefined 0 1 2
    
    var cc = fun(0).fun(1); // undefined 0
    cc.fun(2); // 1
    cc.fun(3); // 1

    内存溢出与内存泄漏

    1.内存溢出

      *一种程序运行出现的错误

      *当程序运行需要的内存超过了剩余的内存时,就抛出内存溢出的错误

    2.内存泄漏

      *占用的内存没有及时释放

      *内存泄漏积累多了就容易导致内存溢出

      *常见的内存泄漏

        i意外的全局变量

        ii没有及时清理的计时器或回调函数

        iii闭包

  • 相关阅读:
    汇编学习笔记(3)[bx]和loop
    C++面试题-概念篇(一)
    命名空间的冷思考
    背包以及装备模块封装的思考
    虚函数,纯虚函数以及虚继承
    组件化开发在游戏开发当中的思考和汇总
    Netty和MINA之间的比较思考
    学习C++与Java之间的区别
    C++服务器年前总结
    C++Builder如何将当前时间与字符串相互转换
  • 原文地址:https://www.cnblogs.com/bobo1/p/14721472.html
Copyright © 2011-2022 走看看