zoukankan      html  css  js  c++  java
  • 嵌套函数和闭包

    你可以在一个函数里面嵌套另外一个函数。嵌套(内部)函数对其容器(外部)函数是私有的。它自身也形成了一个闭包。一个闭包是一个可以自己拥有独立的环境与变量的的表达式(通常是函数)。

    既然嵌套函数是一个闭包,就意味着一个嵌套函数可以”继承“容器函数的参数和变量。换句话说,内部函数包含外部函数的作用域。

    可以总结如下:

    • 内部函数只可以在外部函数中访问。
    • 内部函数形成了一个闭包:它可以访问外部函数的参数和变量,但是外部函数却不能使用它的参数和变量。

    下面的例子展示了嵌套函数:

    function addSquares(a, b) {
      function square(x) {
        return x * x;
      }
      return square(a) + square(b);
    }
    a = addSquares(2, 3); // returns 13
    b = addSquares(3, 4); // returns 25
    c = addSquares(4, 5); // returns 41

    由于内部函数形成了闭包,因此你可以调用外部函数并为外部函数和内部函数指定参数:

    function outside(x) {
      function inside(y) {
        return x + y;
      }
      return inside;
    }
    fn_inside = outside(3); // Think of it like: give me a function that adds 3 to whatever you give it
    result = fn_inside(5); // returns 8
    
    result1 = outside(3)(5); // returns 8

    保存变量

    注意到上例中 inside 被返回时 x 是怎么被保留下来的。一个闭包必须保存它可见作用域中所有参数和变量。因为每一次调用传入的参数都可能不同,每一次对外部函数的调用实际上重新创建了一遍这个闭包。只有当返回的 inside 没有再被引用时,内存才会被释放。

    这与在其他对象中存储引用没什么不同,但是通常不太明显,因为并不能直接设置引用,也不能检查它们。

    多层嵌套函数

    函数可以被多层嵌套。例如,函数A可以包含函数B,函数B可以再包含函数C。B和C都形成了闭包,所以B可以访问A,C可以访问B和A。因此,闭包可以包含多个作用域;他们递归式的包含了所有包含它的函数作用域。这个称之为作用域链。(稍后会详细解释)

    思考一下下面的例子:

    function A(x) {
      function B(y) {
        function C(z) {
          console.log(x + y + z);
        }
        C(3);
      }
      B(2);
    }
    A(1); // logs 6 (1 + 2 + 3)

    在这个例子里面,C可以访问B的y和A的x。这是因为:

    1. B形成了一个包含A的闭包,B可以访问A的参数和变量
    2. C形成了一个包含B的闭包
    3. B包含A,所以C也包含A,C可以访问B和A的参数和变量。换言之,C用这个顺序链接了B和A的作用域

    反过来却不是这样。A不能访问C,因为A看不到B中的参数和变量,C是B中的一个变量,所以C是B私有的。

    命名冲突

    当同一个闭包作用域下两个参数或者变量同名时,就会产生命名冲突。更近的作用域有更高的优先权,所以最近的优先级最高,最远的优先级最低。这就是作用域链。链的第一个元素就是最里面的作用域,最后一个元素便是最外层的作用域。

    看以下的例子:

    function outside() {
      var x = 5;
      function inside(x) {
        return x * 2;
      }
      return inside;
    }
    
    outside()(10); // returns 20 instead of 10

    命名冲突发生在return x上,inside的参数xoutside变量x发生了冲突。这里的作用链域是{insideoutside, 全局对象}。因此insidex具有最高优先权,返回了20(insidex)而不是10(outsidex)。

  • 相关阅读:
    java在线学习-mybatis的缓存类及作用
    java架构师学习路线-MyBatis中的一些概念
    java架构师学习路线-Mybatis中单例模式的介绍
    java架构师学习路线-Mybatis中Builder模式的介绍
    竞赛图中三元环的期望个数
    求一个点前面第一个大于等于当前值的位置
    CF623D Birthday
    联赛模拟测试33
    网络流
    联赛模拟测试32
  • 原文地址:https://www.cnblogs.com/litings/p/7817146.html
Copyright © 2011-2022 走看看