【问题标题】:JS: Nested functions gain a copy of the outer function's parameters?JS:嵌套函数获得外部函数参数的副本?
【发布时间】:2012-11-26 22:11:38
【问题描述】:

因此,通过以下代码,我向自己证明了嵌套函数确实获得了外部函数参数的副本:

    var o = {};
    (function(a,b,c,x){
        x.f = function(){
            return a.toString()+b.toString()+c.toString();
        }
    })(7,4,2,o);
    o.f();

代码生成

    742

这意味着o.f 函数从匿名函数中获得了 a、b 和 c 的副本。否则,我只会得到undefinedundefinedundefined

我的问题是,

  • 首先,这总是正确的吗?还是有严格的条件? (例如,它必须是一个对象吗?等等)
  • 另外,在 javascript 中还有哪些其他类型的模糊作用域?我很想知道(即第三次迭代呢?)
  • 最后,我可以阅读一份解释 JavaScript 作用域高级概念的文档。有谁知道有什么好的吗?

【问题讨论】:

    标签: javascript scope nested-function


    【解决方案1】:

    您需要做的就是阅读闭包。 http://en.wikipedia.org/wiki/Closure_(computer_science) 内部函数并没有获得该变量的副本,而是获得对该变量的引用。示例:

    var o = {};
    (function(a,b,c,x){
        x.f = function(){
            return a.toString()+b.toString()+c.toString();
        }
        a++;
    })(7,4,2,o);
    o.f();
    

    产量

    842

    编辑:好的,也许这不是您需要阅读的全部。我只是认为值得证明这个概念对许多语言来说并不陌生。

    【讨论】:

      【解决方案2】:
      • 是的,这适用于所有类型。 javascript 设计的这个元素称为“闭包”。在谷歌搜索其他阅读材料时使用它。
      • 对于创建函数的嵌套深度没有语言限制,只有可维护性限制。通常在第二级之后你会进入“封闭地狱”或“封闭意大利面”,是时候重构了。因此,您可以将函数嵌套 4 层,并从函数 4 中的代码访问函数 1 的参数。
        • 我想到了另外 2 个“晦涩难懂”的案例:
          • 如果您直接调用函数而没有明确的this 绑定,this 将绑定到全局(窗口)对象。这被普遍认为是 javascript 中的严重缺陷之一。当心。
          • JavaScript 具有“函数提升”功能,这意味着即使实际函数定义在同一范围内的源代码文件中更下方,也可以从范围顶部引用函数。
      • 只需阅读 Douglas Crockford 的 JavaScript: The Good Parts。还有许多很棒的教程和在线书籍免费提供,并且可以通过网络搜索轻松找到。只要确保它们是现代的(大部分时间不早于 2010 年编写)。

      【讨论】:

        【解决方案3】:

        您所观察到的称为词法作用域。这意味着JavaScript中某个范围内的变量的绑定取决于变量在代码中出现的位置。它总是正确的,在任何层面上都是正确的。唯一的主要例外是 this 值,它是动态范围而不是词法范围。动态范围意味着函数中的变量取决于调用函数的方式和时间。 (见Lexical Scoping and Dynamic Scoping。)

        例子:

        var o = { 
            a: function() {
                var x = 5;
                console.log(this, x);
                function b() {
                    console.log(this, x);
                }
                b();
            }
        };
        
        o.a();
        

        这个例子的结果是:

        {Object o} 5
        {window} 5
        

        换句话说,第一个console.log 将记录this 作为对o 对象的引用,而第二个console.log 将记录this 作为对window 对象的引用。但是,两者都会将x 记录为等于5this 的值是 window,当它在没有上下文的非严格模式下调用时。所以this 不是词法范围的,但其他变量,如x 是。要详细了解this 的行为,请参阅A Short Overview of this


        直接回答您的问题:

        1。首先,这总是正确的吗?还是有严格的条件? (比如,它必须是一个对象吗?等等)

        是的,除了 thisarguments 之外,这都是真的,它们会根据函数的调用方式而变化。它不必是一个对象,所有变量都是词法范围的。


        2。此外,在 javascript 中还存在哪些其他类型的模糊范围?我很想知道(即第三次迭代呢?)

        您可以随意深入——内部函数始终可以访问其外部函数的变量。

        function a() {
            var x = 1;
            console.log('a:', x);
            return function b() {
                var y = 2;
                console.log('b:', x, y);
                return function c() {
                    console.log('c:', x, y);
                };
            };
        }
        
        var foo = a();   // => logs 'a: 1'
        var bar = foo(); // => logs 'b: 1 2'
        bar();           // => logs 'c: 1 2'
        

        这实际上是称为closures 的另一个主题的一部分,当您从另一个函数中返回一个函数时会发生这种情况。


        3。最后,我可以阅读一份解释 javascript 范围的高级概念的文档。有谁知道有什么好的吗?

        我已经链接到几个资源。另一个不错的:

        MDN: Functions and function scope(特别是Nested Functions and Closures 部分)。

        此外,阅读有关闭包的任何内容都会使您受益,并且您可能还想查找词法范围

        【讨论】:

          【解决方案4】:

          我在代码中使用这个概念时犯了一个愚蠢的错误,并错误地将参数重新声明为变量。在这里发帖以防对其他人有帮助。

          (function(){
          var outerFunction=function(varA){
              console.debug('value of varA in outer function '+varA);
              var innerFunction = function(){
                  console.debug('value of varA in inner function '+varA);
              }
              innerFunction();
          };
          outerFunction("hi");
          
          var buggyOuterFunction=function(varA){
              console.debug('value of varA in buggy outer function '+varA);
              var buggyInnerFunction = function(){
                  var varA = varA || "hello"; //BUG - do not redeclare
                  console.debug('value of varA in buggy inner function '+varA);
              }
              buggyInnerFunction();
          };
          buggyOuterFunction("hi");
          })();
          

          输出:

          value of varA in outer function hi
          value of varA in inner function hi
          value of varA in buggy outer function hi 
          value of varA in buggy inner function hello
          

          【讨论】:

          • 很高兴认识 - 没想到,但现在我知道要避免它;)
          猜你喜欢
          • 1970-01-01
          • 2017-12-02
          • 1970-01-01
          • 1970-01-01
          • 2018-05-27
          • 2012-11-20
          • 2011-12-17
          • 1970-01-01
          • 2016-06-21
          相关资源
          最近更新 更多