Javascript JS:嵌套函数获得外部函数的副本';s参数?

Javascript JS:嵌套函数获得外部函数的副本';s参数?,javascript,scope,nested-function,Javascript,Scope,Nested Function,因此,通过以下代码,我向自己证明了嵌套函数确实获得了外部函数参数的副本: 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的副本。否则,我只会得到un

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

    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的副本。否则,我只会得到
unfinedunddefinedunddefined

我的问题是,

  • 首先,这总是真的吗?还是有严格的规定?(比如,它必须是一个物体吗?等等)
  • 另外,在javascript中还有什么其他类型的模糊作用域像这样存在?我很想知道(例如,第三次迭代怎么样?)
  • 最后,我很乐意阅读一篇解释javascript范围高级概念的文档。有人知道什么好的吗

您只需阅读闭包。)而内部函数并没有得到该变量的副本,而是得到了对该变量的引用。例如:

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

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

  • 是的,这适用于所有类型。javascript设计的这个元素称为“闭包”。在谷歌搜索其他阅读材料时使用该选项
  • 创建函数的嵌套深度没有语言限制,只有可维护性限制。通常在第二级之后,你会进入“闭包地狱”或“闭包意大利面”,是时候重构了。因此,您可以将函数嵌套到4个级别,并从函数4中的代码访问函数1的参数。
    • 我想到了另外两个“模糊”案例:
      • 如果在没有显式的
        this
        绑定的情况下直接调用函数,
        this
        将绑定到全局(窗口)对象。这被普遍认为是javascript中的一个严重缺陷。当心
      • JavaScript具有“函数提升”功能,这意味着可以从作用域的顶部引用函数,即使实际的函数定义在同一作用域的源代码文件中的较低位置
  • 读一下道格拉斯·克罗克福德的。还有许多很棒的教程和在线书籍,免费提供,通过网络搜索可以轻松找到。只要确保它们是现代的(大部分写在2010年之前)

    • 你观察到的被称为词汇范围。这意味着JavaScript中特定范围内变量的绑定由变量在代码中的位置决定。这永远是真的,在任何层面上都是真的。唯一的主要例外是
      this
      值,它是动态范围的,而不是词汇范围的。动态范围意味着函数中的变量取决于调用函数的方式和时间。(见附件。)

      例如:

      var o = {};
      (function(a,b,c,x){
          x.f = function(){
              return a.toString()+b.toString()+c.toString();
          }
          a++;
      })(7,4,2,o);
      o.f();
      
      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
      作为对
      窗口
      对象的引用。但是,两者都将
      x
      记录为等于
      5
      。在无上下文的非严格模式下调用时,
      this
      的值为
      window
      。因此,
      这个
      不是词汇范围,而是其他变量,如
      x
      是。要了解有关
      this
      行为的更多信息,请参阅


      要直接回答您的问题:

      1.首先,这总是真的吗?还是有严格的规定?(比如,它必须是一个物体吗?等等) 是的,除了
      参数
      之外,这是正确的,它们会根据调用函数的方式发生变化。它不必是一个对象,所有变量都有词汇范围


      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'
      
      这实际上是另一个主题(称为)的一部分,当您从另一个函数中返回一个函数时,会发生这种情况


      3.最后,我很乐意阅读一篇解释javascript范围高级概念的文档。有人知道什么好的吗? 我已经链接到了一些资源。另一个很好的例子是:

      (特别是关于的一节)


      另外,阅读闭包上的任何内容都会让您受益匪浅,您可能还想查找词法范围

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

      (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
      

      很高兴认识到这一点——我没有想到,但现在我知道如何避免;)