【问题标题】:Parameter correspondence: callback vs. closures (?)参数对应:回调与闭包(?)
【发布时间】:2015-12-20 20:33:02
【问题描述】:

对于 javascript 闭包和回调,我对为什么命名的嵌套函数采用的参数与闭包的参数不同(从外部函数继承?)之间的区别感到困惑。例如:

var filter = function (collection, test) {
    var newArray = [];
    each(collection, function (value) {
        if (test(value)) { 
            newArray.push(value);
        }
    });
    return newArray;
};

过滤器函数对每个函数进行操作。 “值”参数(在每个中)对应于什么输入?回调函数的参数是否自动与过滤器的第一个参数对齐,因为它们都是各自函数的第一个参数?如果外部函数和内部函数都接受另一个参数,那么它们也会因为它们的位置而排列吗?这里的内部/外部函数之间的参数关系似乎与闭包的参数不同(闭包似乎接受了一个新参数;它的参数与外部的参数不对齐)例如:

var outer = function(par1, par2) {
    var hold = par1 + par2;

    function inner(par3) {
       return par3 + par1 + par2;
    }
    return inner;
};

var closure = outer (5,4);

closure(2);

我看到内部函数是从外部函数返回的(当存储在另一个变量中时),并且将自己的参数与外部函数分开。

命名/建立函数是否从其封闭函数继承其参数对应关系?

回调函数是否采用自己的参数 - 与它们的封闭函数分开 - 因为它们是从该函数返回并保存到变量中的?

【问题讨论】:

    标签: javascript parameters callback nested closures


    【解决方案1】:

    “value”参数(在每个中)对应什么输入?

    这取决于each 的作用。它不是标准的 JS 全局变量,您还没有分享您对它的定义。

    回调函数的参数是否自动与过滤器的第一个参数对齐,因为它们都是各自函数的第一个参数?

    没有。传递给任何函数的参数取决于调用该函数的代码。

    如果外部函数和内部函数都接受另一个参数,它们是否也会因为它们的位置而排队?

    没有。

    命名/建立函数是否从其封闭函数继承其参数对应关系?

    没有。

    回调函数是否接受自己的参数 - 与它们的封闭函数分开

    是的

    因为它们是从该函数返回并保存到变量中的?

    没有。因为它们是函数。

    function outer(foo, bar) {
      console.log("Outer gets foo " + foo + " because foo is a argument of outer");
    
      console.log("Outer gets bar " + bar + " because foo is a argument of outer");
    
      return inner;
    
    
      function inner(baz) {
        console.log("Inner gets foo " + foo + " because foo is a variable still in scope");
        console.log("Inner gets bar " + bar + " because bar is a variable still in scope");
        console.log("Inner gets baz " + baz + " because baz is an argument of inner");
      }
    
    }
    
    var returned_inner = outer(1, 2);
    returned_inner(3);

    对于 javascript 闭包和回调,我对为什么命名的嵌套函数采用的参数与闭包的参数不同(从外部函数继承?)之间的区别感到困惑。

    您的混淆问题源于一个简单的事实,即在大多数情况下,当您使用回调时,实际调用它的函数由其他人编写并且您从不查看在它

    【讨论】:

      【解决方案2】:

      我想我可以这样总结所有问题的答案:内部函数的参数完全不需要与封闭函数的参数有任何关系。

      它们是完全不相关的值。

      例如:

      function f(a, b, c, d, e) {
          // You mentioned "named, nested" function in your question...
          return function unusedName(x) {return x}
      }
      console.log(f(1, 2, 3, "four", 25/5)(100));
      

      将显示 100。

      当然,在现实中,你会希望内部函数以某种方式使用外部函数的参数,否则外部函数的参数是无用的。

      但并不要求他们“排队”。如何创建闭包,即返回的内部函数如何决定使用外部函数提供的环境中的值,完全取决于您。语言本身什么都不强制。

      【讨论】:

        【解决方案3】:

        请考虑更改问题中的大部分假设 :-)

        标识符范围。

        当 javascript 代码在函数内部使用未经修饰的标识符(例如变量名、对象名或函数名)时,javascript 引擎会查看该标识符是否是局部变量的名称,定义在同一函数体内的嵌套函数的名称,或形式参数的名称。如果未找到,它将以相同的方式在下一个最外部的函数中搜索标识符(如果搜索的函数是嵌套的),或者如果搜索的最后一个函数本身是全局的,则在全局范围内查找标识符。

        因此没有嵌套函数参数的“排列”,只是搜索作用域链。外部函数参数、变量和命名函数定义都在内部函数的范围内。除非程序员计划,否则不同函数中的形参定义之间没有自动的“关系”。

        关闭

        注意将函数归类为回调闭包。通常一个回调函数会形成一个闭包。总之,闭包是由于在其外部函数返回后保持对嵌套函数的引用而引起的。这可能是由于在外部函数返回之前或之后存储对内部函数的引用,或者将内部函数的引用传递给其他函数以用作异步回调。只要对内部函数的引用被保存在某个地方,它在其作用域链中引用的任何值都不能用于垃圾回收,因为它们是可访问的。

        forEach

        each 函数似乎是一个迭代器函数,应用于作为参数传递的集合。 Javascript 支持标准化的forEach 来迭代 Array、Map 和 Set 对象。调用方式及回调回调函数请参考documentation

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-02-15
          • 2015-12-28
          • 1970-01-01
          • 2015-05-22
          • 1970-01-01
          • 2022-10-21
          • 2012-12-08
          相关资源
          最近更新 更多