OO Javascript和这个关键字。对象文字

时间:2011-11-15 02:14:46

标签: javascript

我遇到了Javascript属性和“this”关键字问题。请原谅我在这里询问我的第三个也是最后一个JS OOP问题。 Javascript中的OOP今天让我头疼。

我正在尝试设置属性'source',但错误控制台说它在parseSource方法中未定义。

经过一番研究后,我相信this.source是指window.source?代码是Mozilla的样板。创建扩展时,初始化插件时,FireFox会调用init。

使用文字符号创建对象时,设置属性的最佳方法是什么?

var myExtension = {
source: null,

init: function() {  
    // The event can be DOMContentLoaded, pageshow, pagehide, load or unload.  
    if(gBrowser) {
        gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false);  
    }
},  

onPageLoad: function(aEvent) {  
    doc = aEvent.originalTarget; // doc is document that triggered the event  
    win = doc.defaultView; // win is the window for the doc  

    // Skip frames and iFrames
    if (win.frameElement) return;

    this.source = win.document.getElementById('facebook').innerHTML;
    myExtension.parseSource();
},

parseSource: function() {
    if(this.source == null) {
        // So something
    } else {
        // Do something else
    }
}
}  

window.addEventListener("load", function() { myExtension.init(); }, false);  

2 个答案:

答案 0 :(得分:1)

当您将回调函数传递给gBrowser.addEventListener时,如下所示:

gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false);  

您正在传递对该函数的引用,该函数基本上是"已分离的"来自定义它的this对象。因此,您需要执行以下操作才能正确维护this引用:

init: function() {  
    var self = this;
    if(gBrowser) {
        gBrowser.addEventListener("DOMContentLoaded", function () {
            self.onPageLoad();
        }, false);  
    }
},

在较新的浏览器中(您确实说这是FF扩展名),您可以使用Function.bind来达到同样的效果:

init: function() {
    if(gBrowser) {
        gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad.bind(this), false);  
    }
},

清除完毕后,您可以将onPageLoad功能更改为:

onPageLoad: function(aEvent) {  
    doc = aEvent.originalTarget; // doc is document that triggered the event  
    win = doc.defaultView; // win is the window for the doc  

    // Skip frames and iFrames
    if (win.frameElement) return;

    this.source = win.document.getElementById('facebook').innerHTML;
    this.parseSource();
},

修改

精简版演示:http://jsfiddle.net/mattball/bDe6N/

答案 1 :(得分:0)

问题是Javacript中的方法如果将它们作为参数传递,就会忘记它们this。它们只有在你看起来像一个方法传递它们时才能工作

//this doesn't work in JS
f = obj.method
f()
//wtf man! You have to call it looking like a method
obj.method()

在您的情况下,这是因为您将this.onPageLoad作为参数传递。函数参数的作用类似于上一个示例中的变量。

解决方法是使用包装函数来保留方法调用外观

addEventListener( ..., function(){ return this.onPageLoad(); }, ...)

除了this不是lexicaly作用域,内部函数也得到错误的副本。经过另一次快速解决后,我们获得了

var that = this;
addEventListener(..., function(){ that.onPageLoad(); }, ...);

这应该可以胜任。