模式来处理“这”在JavaScript事件处理程序
我想要封装了一些代码获取并使得在必要时释放的标签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)作为变量的结果,但它没有帮助,现在正在努力寻找选项。
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
解决方法:请勿使用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
。
function MyHandler_onLoad()
{
var self = this;
完成此操作后,self
将始终指向您的处理程序中正确的对象。
这似乎解决了它,但我认为我需要使用新的,因为我想处理单独的MyHandler_onLoad对象中的每个多个选项卡。 – Mat 2011-04-24 19:24:24
@Mat,是的,你不再需要'新'。您只需在原型方法中使用“新”,这不再是推荐的方法(因为OO不再是推荐的方法) – Halcyon 2011-04-24 19:43:55