JavaScript中的“this”作用域

4

我在写一些JavaScript代码,对于this关键字还有点困惑。在dataReceivedHandler函数中如何访问logger变量呢?

MyClass: {
    logger: null,
    init: function() {
        logger = LogFactory.getLogger();
    },
    loadData: function() {
        var dataReceivedHandler = function() {
            // how to access the logger variable here? 
        }

        // more stuff
    }
};
3个回答

10

你可以在loadData函数内部像这样做,以访问你的对象...

MyClass: {
    logger: null,
    init: function() {
        this.logger = LogFactory.getLogger();
    },
    loadData: function() {
        var self = this;
        var dataReceivedHandler = function() {
            // how to access the logger variable here? 
            self.logger.log('something');
        }

        // more stuff
    }
};

6
假设 loadData 被这样调用:
MyClass.loadData();

那么:

loadData: function() {
    var self = this;
    var dataReceivedHandler = function() {
        self.logger ...
    }

    // more stuff
}

4
因为dataReceivedHandler是一个匿名函数,this将指向全局作用域中的窗口对象。我认为有两种方法可以绕过这个问题。
a)在loadData内创建一个变量来保存其上下文,然后在dataReceivedHandler内使用它,如下所示:
loadData: function() {
    var self = this;
    var dataReceivedHandler = function() {
        console.log(self.logger);
    }

    // more stuff
}

b) 使用applycall更改您的匿名函数的上下文。

loadData: function() {
    var dataReceivedHandler = function() {
        console.log(this.logger);
    }
    // more stuff
    dataReceivedHandler.call(this); // by passing this as the first argument we make sure the context of the excuted function is our current scope's this
}

我更喜欢选项B,因为它进行了性能和内存使用的优化,但两个选项都可以正常工作。


2
由于dataReceivedHandler是一个匿名函数,所以 this 将指向全局作用域的 window 对象。当您通过名称 dataReceivedHandler 引用它时,它不再是匿名的。无论是否匿名,this 的值取决于该函数被调用的方式,而不是定义方式(正如您可能已经知道的第二个示例)。请注意,只有在以将其 this 设置为 MyClass 对象的方式调用 loadData() 时,您答案中的两种方法才有效。 - nnnnnn
1
在不使用名称并将其返回到变量中声明函数时(使用function() {}而不是function name() {}),这就是所谓的匿名函数。匿名函数的上下文始终为window,除非通过诸如callapply之类的方法进行覆盖。我错了吗?如果是,请提供一个证明相反的例子。 - iMoses
虽然我没有提到,在我的示例中,当ajax请求完成时,dataReceivedHandler将被调用。在这种情况下,选项B仍然是更好的选择吗? - bluetech
如果您正在构建大型应用程序,则最好在编写代码和设计适合您的编程风格时考虑这些事情。通常,您可以始终使用选项A,如果您仍然想要优化内存使用量,则在执行ajax调用后仅取消设置self即可。您可以通过使用self = undefined来实现这一点,这将使垃圾收集器更容易地摆脱数据/引用(如果需要的话)。 - iMoses
1
@iMoses - 当你声明一个没有名字的函数时,那就是一个函数表达式,而不是一个声明。;-) - RobG
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接