2011-04-24 117 views
0

我想要封装了一些代码获取并使得在必要时释放的标签onLoad事件的Firefox扩展,我呼吁:模式来处理“这”在JavaScript事件处理程序

var onLoad = new MyHandler_onLoad(); 

然后当我做,我呼吁:

onLoad.unregister(); 

原则,直到你深入到更坚韧细节这段代码实现了上述罚​​款。

function bind(scope, fn) { 
    return function(){ 
    fn.apply(scope, arguments); 
}; 

function MyHandler_onLoad() 
{ 
    this.scan = function() { 
     do_scan(this.browser); // this.browser == undefined 
    }; 

    this.register = function() { 
     this.tab.addEventListener("load", this.scan, false); 
    }; 

    this.unregister = function() { 
     this.tab.removeEventListener("load", this.scan, false); 
    }; 

    this.tab = gBrowser.selectedTab; 
    this.browser = gBrowser.selectedBrowser; 
    this.register(); 
    window.addEventListener("unload", bind(this, this.unregister), false); 
}; 

由于JavaScript的行为this,我很挣扎。我希望能够从我的扫描功能访问this.browser,但不能。

我已使用bind确保unregister获得unload的相应上下文。但是,我无法通过拨打scan来做到这一点,因为如果我没有名字,我将无法在以后删除它。

在JavaScript中做这种事情有没有好的模式?

我试过在构造函数中存储bind(this,this.scan)作为变量的结果,但它没有帮助,现在正在努力寻找选项。

回答

3

this,在JavaScript中,始终指向当前对象。如果没有当前对象,this指向window,这是总是顶层范围(在浏览器中无论如何)

例如:

function(){ 
    ... 
    this.foo = function(){ 
     this; 
     // There is no object here, so `this` points to `window` 
    } 
} 

function foo(){ 
    this; 
    // again, no object so `this` points to window` 
} 
foo(); 

function foo(){ 
    this; 
    // because initialized with `new`, `this` points to an instance of `foo` 
    this.bar = function(){ 
     this; 
     // no object, `this` points to `window` 
    } 
} 
var foobar = new foo(); 
// above is roughly equivalent to: foo.apply({}, arguments); Note the new object 

foobar.bar(); 

var foo = { 
    bar : function(){ 
     this; 
     // `this` points at `foo` -- note the object literal 
    } 
}; 

function foo(){ 
} 
foo.prototype.bar = function(){ 
    this; 
    // `this` points to the instance of `foo` 
} 
var foobar = new foo(); 
foobar.bar(); 

结合让你锁定到任何你想要的,因为给函数的最终调用是通过.apply(scope, params)this变量,所以回到你原来的问题的概念,我上面的最后一个例子将工作,所以会这样:

function foo(){ 
    this.scan = bind(this, function(){ 
     this; 
     // `this` points to instance of `foo` IF `foo` is instantiated 
     // with `new` keyword. 
    }); 
} 
new foo() 

如果你想了解所有这个多了,我有两篇文章,我写回的青睐,应可帮助:

http://www.htmlgoodies.com/primers/jsp/article.php/3600451/Javascript-Basics-Part-8.htm http://www.htmlgoodies.com/primers/jsp/article.php/3606701/Javascript-Basics-Part-9.htm

0

解决方法:请勿使用this

我们首先要定义MyHandler_onLoad

function MyHandler_onLoad() { 
    var onload_handler = { 
     scan: function() { 
      do_scan(onload_handler.browser); // onload_handler.browser == undefined 
     }, 
     register = function() { 
      onload_handler.tab.addEventListener("load", onload_handler.scan, false); 
     }, 
     unregister = function() { 
      onload_handler.tab.removeEventListener("load", onload_handler.scan, false); 
     } 
    }; 
    onload_handler.tab = gBrowser.selectedTab; 
    onload_handler.browser = gBrowser.selectedBrowser; 
    onload_handler.register(); 
    window.addEventListener("unload", bind(onload_handler, onload_handler.unregister), false); 
    return onload_handler; 
} 

更妙的是另一种方式?将全局依赖关系向上移动,并且无法访问选项卡和浏览器属性(即,使其成为'私人')

您甚至可以选择隐藏注册和取消注册功能,因为我不确定您是否需要它们,本身已经。

var handler = MyHandler_onLoad(gBrowser.selectedTab, gBrowser.selectedBrowser); 

function MyHandler_onLoad(tab, browser) { 
    var onload_handler = { 
     scan: function() { 
      do_scan(browser); // browser == undefined 
     }, 
     register = function() { 
      tab.addEventListener("load", onload_handler.scan, false); 
     }, 
     unregister = function() { 
      tab.removeEventListener("load", onload_handler.scan, false); 
     } 
    }; 
    onload_handler.register(); 
    window.addEventListener("unload", bind(onload_handler, onload_handler.unregister), false); 
    return onload_handler; 
} 

具体与this您的问题是,它指向的扫描功能,不是你的处理程序对象。如果您根本不使用this,那么您将永远不会遇到这些类型的错误。

哦,你也不需要使用new

+0

这似乎解决了它,但我认为我需要使用新的,因为我想处理单独的MyHandler_onLoad对象中的每个多个选项卡。 – Mat 2011-04-24 19:24:24

+0

@Mat,是的,你不再需要'新'。您只需在原型方法中使用“新”,这不再是推荐的方法(因为OO不再是推荐的方法) – Halcyon 2011-04-24 19:43:55

1
function MyHandler_onLoad() 
{ 
    var self = this; 

完成此操作后,self将始终指向您的处理程序中正确的对象。