【问题标题】:Referring a member variable from self invoking nested function从自调用嵌套函数中引用成员变量
【发布时间】:2012-02-12 09:27:24
【问题描述】:

我有这段代码

var f = function() {
    this.x = 100;
    (
        function() {
            x = 20;
        }
    )();
};

var a = new f;
console.log(a.x);

我想知道为什么在全局范围内创建了一个新变量 x,并且输出是 100,而不是 20。 如果我改写

变量 x = 100;

嵌套函数改变了相同的 x 值。 似乎通过

创建 x

this.x = 100

将 x 置于函数 f 的范围之外。如果是这样,它在哪里定义?以及如何访问?

编辑:修正了一个错字:console.log(a.x) 而不是 console.log(x)

【问题讨论】:

    标签: javascript nested-function


    【解决方案1】:

    声明:

    this.x = 100;
    

    不在当前范围内创建变量,它在this所指的任何对象上设置属性x。在您的情况下,this 将是刚刚通过 new f 实例化的对象,与 f 返回并分配给 a 的对象相同。

    当你说:

    x = 20;
    

    JavaScript 在当前作用域中查找x,但没有找到,因此它会在下一个作用域中查找,依此类推,直到到达全局作用域。如果它在任何可访问的范围内都找不到x,它会创建一个新的全局变量,如您所见。

    要从嵌套函数中访问属性 x,通常的做法是将对 this 的引用存储在局部变量中,然后嵌套函数可以引用该变量:

    var f = function() {
        var self = this;       // keep a reference to this
    
        this.x = 100;
        (
            function() {
                self.x = 20;   // use the self reference from the containing scope
            }
        )();
    };
    
    var a = new f;
    console.log(a.x);          // will now be 20
    

    另一种方法是在内部函数中引用this.x,前提是您通过.call() method 调用内部函数,这样您就可以将this 显式设置为与(外部)中的相同f函数:

    var f = function() {
        this.x = 100;
        (
            function() {
                this.x = 20;
            }
        ).call(this);
    };
    
    var a = new f;
    console.log(a.x);
    

    进一步阅读:

    【讨论】:

    • 解释的很好,还教我call()方法!
    【解决方案2】:

    在 javascript 中,变量具有函数级范围。另外,这个:

    this.x = 100;
    

    不同于:

    x = 20;
    

    因为在后面的情况下,x 具有全局(您之前没有使用过var)范围,例如它成为window 对象的一部分。


    当你在做的时候:

    var a = new f;
    console.log(x);
    

    您正在访问通过x = 20; 设置的全局变量x,而您应该这样做:

    var a = new f;
    console.log(a.x);
    

    【讨论】:

    • 这是一个错字,我的意思是 console.log(a.x),对不起。
    • 有什么方法可以让 'x=20' 引用 'this.x' 而不是在全局范围内创建一个新的 'x'?
    【解决方案3】:
    var f = function() {
    
        this.x = 100;
        console.log(this);
        // f
    
        (function() {
          console.log(this);
          // DOMWindow. So x is a property of window because you're not declaring it with var
          x = 20;
        })();
    };
    

    如果您想将匿名函数的乘积分配到f 的范围内,那么以下将起作用:

    var f = function() {
        this.x = (function() {
          var x = 20; // Local scope
          return x;
        })();
    };
    
    console.log( (new f().x) );
    

    【讨论】:

      【解决方案4】:

      如果您想更改嵌套匿名子函数中的成员函数,您可能需要在范围内创建指向“this”的指针,如下所示:

      var f = function() {
          this.x = 100; // set the member value
          var self = this; // pointer to the current object within this function scope
          (
              function(){
                  self.x = 20; // 'self' is in scope
              }();
          )();
      };
      
      var a = new f;
      
      console.log(a.x); // Output: 20
      

      【讨论】:

        【解决方案5】:

        当您声明一个没有var 的变量时,该变量处于全局范围内。

        【讨论】:

        • 是的,但它的父作用域确实有一个名为 x 的变量(通过 this.x 声明和定义)。它不应该提到那个吗?还是 this.x 在其他地方有效地声明了它?
        • @kaustubh 不,不是指那个。
        猜你喜欢
        • 2013-10-17
        • 2018-11-24
        • 1970-01-01
        • 2020-08-09
        • 1970-01-01
        • 1970-01-01
        • 2018-05-25
        • 1970-01-01
        • 2022-11-27
        相关资源
        最近更新 更多