【问题标题】:Javascript: got 'undefined' when using 'this' to access outer scope variable in 'private' child functionJavascript:使用“this”访问“私有”子函数中的外部范围变量时出现“未定义”
【发布时间】:2013-03-18 20:59:35
【问题描述】:

我习惯于将所有变量设置为其父作用域,而不是隐式调用它们:

function outer() {
    var x, y;
    function inner() {
        var x = this.x;
        x = ...// doing stuff here
        y = ....// implicit calling parent variable
    }
}

这样,如果我输入错误的变量,它就不会进入全局空间。但似乎在私有函数中使用this 声明变量将返回我undefined

function f() {
    var x = [0];
    function f1() { 
        console.log('f1:', this.x, x); 
        f2(); 
    }
    function f2() { 
        console.log('f2:', this.x, x); 
    }
    return { x:x , f1:f1 };
}

var foo = f();    
foo.f1();
    //output
    f1: [0] [0]
    f2: undefined [0]

如果我理解正确,它不应该发生,因为f1f2 都应该可以使用this 访问其外部范围。我在这里缺少任何概念吗?还是我现在只能忍受?

更新:澄清一下,我主要关心的是为什么f1f2 之间存在差异。我更喜欢将f2 隐藏起来,因为它会做一些内部工作,而其他开发人员在从f() 声明某些内容时不应该使用它。

【问题讨论】:

  • this in f2f1,而不是 outer
  • this 是函数的执行上下文,而不是函数的内部范围。当您调用 foo.f1() 时,内部的 f1() this 指的是 foo。如果你想在内部函数中使用来自父作用域的变量,只需按名称引用它们——不带this
  • 你应该试试这本书:packtpub.com/object-oriented-javascript/book.
  • 您忘记在 f1 函数中添加 var x = this.x;

标签: javascript this scope


【解决方案1】:

也试试这个:

function f() {
    var x = [0];
    function f1() { 
        console.log('f1:', this.x, x); 
        f2.call(this); 
    }
    function f2() { 
        console.log('f2:', this.x, x); 
    }
    return { x:x , f1:f1 };
}

var foo = f();    
foo.f1();

这样会正确设置 f2 的上下文。

在您的代码中,f2 中的this 指的是窗口对象,因为 f2 没有被声明为方法。 f1 在编写{ x:x , f1:f1 } 时被声明为返回对象的方法。在 f2 中 x 是可见的,不是因为它在 f() 的范围内运行,而是因为 f2 将它作为闭包。这意味着在 f2 中,所有在创建时位于同一范围内的变量都是可见的。

this 所指的内容将在调用时设置。如果您将函数作为foo.f1() 之类的对象的属性运行,则它被视为一种方法,并且this 将被设置为该对象。但是,当您只是调用像 f2() 这样的函数时,其作用域将与调用时相同,在您的情况下它是窗口对象,因为 foo 是窗口对象中的全局对象。

在 f1 中,这指的是隐藏的 f(),因此如果您希望 f2 也可以在该范围内运行,您可以使用 f2.call(this)。 .call() 的参数将是函数运行时的this

【讨论】:

  • 感谢您的解决方案,非常感谢您提供清晰而全面的解释。我现在将其标记为答案。
【解决方案2】:

当您的f 函数返回一个对象时,它没有f2 方法。 f2 方法是f 的内部方法,只存在于其作用域内。

如果您使用此代码:

function f() {
    var x = [0];
    function f1() { 

        console.log('f1:', this.x, x); 
        this.f2(); 
    }
    function f2() { 
        console.log('f2:', this.x, x); 
    }
    return { x:x , f1:f1, f2:f2};
}

var foo = f();    
foo.f1();

那么f1方法中的this就可以访问thisf2方法,对象的f2方法会返回正确的x

【讨论】:

  • 我希望隐藏f2,以免人们意外使用它。 @Sylvanus 的解决方案解决了我的问题。但是,您在我的问题下方的评论对我来说似乎是合理的。所以我按照它并进行了一些测试以确认我的理解:jsfiddle.net/PbPbz 我在f1 中放置了一个变量a,所以现在如果f2 中的this 参考f1,那么我应该可以看到它在f2。但似乎并非如此。
  • 在那个小提琴 f2 中的 this 指的是窗口对象,因为 f2 没有被声明为方法。 f1 在写入 { x:x , f1:f1 } 时被声明为返回对象的方法
  • 在 f2 中 x 可见不是因为它在 f() 的范围内运行,而是因为 f2 将其作为闭包。这意味着在 f2 中,创建时位于同一范围内的所有变量都是可见的。
【解决方案3】:

你从函数中返回了这个:

{ x : x, f1 : f1 }

这会将this 对象属性设置为上述属性。 f2 不是对象的一部分,因此它无法访问它所引用的 this

【讨论】:

    猜你喜欢
    • 2014-05-29
    • 2012-06-17
    • 2013-12-07
    • 2019-10-05
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 2016-05-20
    • 2011-08-23
    相关资源
    最近更新 更多