【问题标题】:JavaScript Closure problem again!JavaScript 闭包问题又来了!
【发布时间】:2011-06-28 21:28:33
【问题描述】:

这就是我面临的问题

函数 AAA(){ this.f1 = 函数(){ /*期望 f2 将被调用,因为两者都是同一个对象。*/ 控制台.log(f2(5));// } this.f2 = 函数(x){ 返回 x; } } x = 新 AAA(); x.f1(); //ReferenceError: f2 未定义

也不行,

函数 AAA(){ this.f1 = 函数(){ /*期望 f2 将被调用,因为两者都是同一个对象。*/ 控制台.log(f3(5));// } /*命名函数f3希望得到函数引用,作为函数 右边有名字现在和f1的关闭,对吧?*/ this.f2 = 函数 f3(x){ 返回 x; } 函数 f4() {}; } x = 新 AAA(); x.f1(); //ReferenceError: f3 未定义

这里发生了什么?除了“f4”之外,还有谁在关闭“f1”?我们不能在没有'this'的情况下调用同一个对象函数吗?

【问题讨论】:

    标签: javascript closures


    【解决方案1】:

    你在这里并没有真正使用闭包。如果您将行更改为

    ,它将正常工作
     console.log(this.f2(5));
    

    如果你想使用闭包,你可以重写类如下:

    function AAA()
    {
        var f1 = function()
        {
            console.log(f2(5));
        };
    
        // f2 is a private function.
        var f2 = function(x)
        {
            return x;
        };
    
        // Define the public interface.
        return { f1: f1 };
    }
    

    【讨论】:

    • 是的,我明白了你的意思,但我想知道谁在关闭 f1,或者为什么我们不能在没有“this”的情况下调用相同的对象函数?机制是什么。
    • @abdullah829:在其他语言中,如果您指的是同一对象的另一个成员,则可以省略“this”。你不能在javascript中做到这一点。如果你只写“f2”并省略“this”,那么 javascript 会开始寻找具有这个名称的局部变量,然后在作用域链中向上(闭包),最后它会查看全局作用域(窗口对象) .
    • 没关系!那么谢谢你,如果你像第二个例子一样命名一个函数会发生什么......名称是f3,如果你没有将它分配给this.f2它会正常工作吗?对
    【解决方案2】:

    您在这里混淆了一些事情; this 和闭包是两个完全不同的问题。

    你的问题是你试图直接引用f2,从而假设this是当前执行范围的一部分。 不是
    如果您将f2 放在this 上,则必须继续将其引用为this.f2。为了能够直接引用f2,您必须使用该名称声明一个(单独的)变量,然后您可以根据需要将其分配给this,正如qwertymk 所说。

    就我个人而言,我尽量避免使用this,因为它的含义完全取决于函数的调用方式(例如,如果在没有指定new 运算符的情况下调用AAAthis 将参考全局对象!)。它还可以使您免于上述头痛。闭包(如 Elian 所示)是获得此功能的更好方法。
    有趣的是,我发现我几乎没有需要使用this

    在 Elian 的示例中,f2关闭:一旦 AAA 函数运行完毕,除了在 AAA 中定义的函数(并且仍然可以访问)之外,没有人可以访问 f2。在这种情况下,函数f1 可以从返回的对象中访问,所以它仍然存在。因此,f1 仍然可以使用f2
    这就是闭包的意义:一个函数仍然可以访问其范围内的所有变量,即使这些变量是在一个终止的函数中声明的。

    【讨论】:

      【解决方案3】:

      它本身应该是this.f2() 而不是f2()。如果 f2() 是私有变量,则您将使用它,这意味着如果它是使用 var 关键字创建的。

      function AAA(){
          var f3 = function(x) { return x; };
          this.f1 = function (){
              /*expecting that f2 will be call as both of then are of same object.*/
              console.log(this.f2(5));//
              console.log(f3(10));
          }
      
          this.f2 = function(x){
              return x;
          }
      }
      

      DEMO

      【讨论】:

      • 正是 qwertymk 提到的原因:对 this.f2 的赋值不会创建名为 f2 的变量,但您的代码会尝试访问名为 f2 的变量(!)。
      • @Chistopher 当我将函数命名为 f3 时,第二个示例会发生什么?
      【解决方案4】:

      其他人已经告诉过你问题是什么,所以我不再重复。如果你想让你的代码工作,你只需要一个参考:

      function AAA(){
          var self = this;
          this.f1 = function (){
              console.log(self.f2(5)); //self.f2 exists, yay
          }
      
          this.f2 = function(x){
              return x;
          }
      }
      
      x = new AAA();
      x.f1(); //5
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-09
        • 2013-02-17
        • 1970-01-01
        • 2021-07-01
        • 1970-01-01
        相关资源
        最近更新 更多