【问题标题】:JavaScript give called function access to calling function variablesJavaScript 赋予被调用函数访问调用函数变量的权限
【发布时间】:2016-06-05 15:09:15
【问题描述】:

如果我在函数内部定义了内部函数,则内部函数可以访问外部函数的变量。如果我希望这个内部函数可重用并在外部函数之外定义它,则内部函数现在无法访问外部函数变量。如何使这个新的可重用内部函数能够访问外部函数变量,而不将这些变量作为参数传递?

        function a () {

        var x = [[1,2,3], [1,2,3], [1,2,3]];

        var keys = Object.keys(x[0]);

        for (var i = 0; i < x.length; i++) {
            angular.forEach(keys, loop);
        }

        }

        function loop (key) {
            console.log(key, i);//i is undefined here
        }
        a();

具体来说,有没有什么方法可以不 1) 为其分配变量,2) 不将变量作为参数传递,以及 3) 不创建全局变量?

编辑:似乎没有办法做到这一点。但是如果我尝试另一种方法,让可重用函数返回一个新函数,我也无法访问内部范围。为什么会这样,有什么方法可以实现吗?

        function a () {

        var x = [[1,2,3], [1,2,3], [1,2,3]];

        var keys = Object.keys(x[0]);
        var myloop = loop();

        for (var i = 0; i < x.length; i++) {
            angular.forEach(keys, myloop);
        }

        }

        function loop (key) {
            return function(key) {
                 console.log(key, i);//i is undefined here
            };
        }
        a();

【问题讨论】:

  • 可以使用全局变量,虽然不推荐。
  • 除了使用全局变量还有什么办法?我认为闭包一定有某种方法,但我无法让它发挥作用。
  • 使可重用函数依赖于其范围之外的变量对我来说似乎是一个非常糟糕的主意。将i 传递给函数有什么问题?
  • 问题是您需要创建一个匿名函数来执行此操作。 angular.forEach(keys, function(key) { loop(key, i)})
  • 这个函数应该完成什么?所以keys 包含x 中第一个数组的键(或索引值)。然后你迭代a 的长度(函数的长度为零,所以循环永远不会运行),如果循环以某种方式执行,你再次循环键。你能澄清一下吗?

标签: javascript scope closures


【解决方案1】:

我还想知道我刚刚发现的另一个选项。如果使用.bind,可以用i对函数进行curry,其他变量会在curried参数之后传入。

 ....
 angular.forEach(keys, loop.bind(null, i));
 ...

 function loop(i, key) {
 ...
 }

【讨论】:

    【解决方案2】:

    在下面的示例中,loop 返回一个关闭 i 值的函数。

    function a () {
        var x = [[1,2,3], [1,2,3], [1,2,3]];
    
        var keys = Object.keys(x[0]);
    
        for (var i = 0; i < keys.length; i++) {
            keys.forEach(loop(i));
        }
    }
    
    function loop (i) {
        return function (key) {
            console.log(key, i);  // i is now defined
        }
    }
    
    a();
    

    输出:

    0 0
    1 0
    2 0
    0 1
    1 1
    2 1
    0 2
    1 2
    2 2
    

    【讨论】:

    • 这是最接近的解决方案,因此将其标记为正确。
    【解决方案3】:

    如何使这个新的可重用内部函数能够访问外部函数变量,而不将这些变量作为参数传递?

    你不能。 JavaScript 有lexical scope,不是动态范围。

    另见:What is lexical scope?

    【讨论】:

      【解决方案4】:

      在 JS(和许多其他语言)中,存在可见性上下文。可能的上下文是例如“全局”或功能或块。这些上下文是分层的,内部可以读取外部。除非内部将变量声明为全局变量,否则外部永远无法读取内部(封装原则)。

      【讨论】:

        【解决方案5】:

        内部函数由外部函数局部处理。因此,您可以从内部函数访问属于外部函数的变量。但是,一旦您将内部函数作为外部函数之外的单独函数,您就无法再访问外部函数的私有数据变量。

        如果这看起来很复杂,这里有一个例子:

        function A
        {
          //variables
          function B
          {
           can use variables of A
          }
        }
        

        但是,

            function A
            {
              //variables
            }
            function B
            {
             //cannot access variables of A
            }
        

        【讨论】:

          猜你喜欢
          • 2014-10-04
          • 2017-07-12
          • 2013-11-27
          • 1970-01-01
          • 2016-02-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多