到目前为止,我已经设法避免在我的大部分 javascript 开发中使用命名空间,但我开始通过阅读有用的文章(如 this one)看到曙光。
我正在关注 Maeagers 技术 found here创建我的命名空间,如下所示 -
var newAndImproved = {
//div to put loaded content into
targetDiv: "",
//loads the initial content based on an anchor tag having a class named 'chosen'
loadInitialPage: function() {
var chosenLink = $("#subnavigation a.chosen");
newAndImproved.loadPartial(chosenLink);
},
loadPartial: function(clickedLink) {
var theUrlToLoad = $(clickedLink).attr("href");
$(newAndImproved.targetDiv).load(theUrlToLoad, function(response, status, xhr) {
if (status == "error") {
var msg = "Sorry but there was an error: ";
$(targetDiv).html(msg);
}
});
},
removeClassFromSubNav: function() {
$("#subnavigation a").removeClass('chosen');
},
addChosenClassToNav: function(chosenLink) {
$(chosenLink).addClass('chosen');
},
bindMethodsToNavigation: function() {
$("#subnavigation a").bind('click', function(event) {
var chosenLink = event.target;
newAndImproved.removeClassFromSubNav();
newAndImproved.loadPartial(chosenLink);
newAndImproved.addChosenClassToNav(chosenLink);
return false;
});
}
};
我这样称呼那个命名空间 -
$(document).ready(function() {
newAndImproved.targetDiv = $("#subcontent");
newAndImproved.loadInitialPage();
newAndImproved.bindMethodsToNavigation();
});
我相信您已经注意到我引用的是 namespace 本身,而不是仅仅使用“this”。我认为这是不正确的。但是当我使用“this”时,绑定(bind)部分将不起作用。
奇怪的是,loadInitialPage 方法在使用“this”时会起作用。
知道我做错了什么吗?
提前致谢。
最佳答案
您需要使用that
技巧。 this
在新范围内被重新分配,包括您正在绑定(bind)的匿名函数。
考虑这段代码:
function say(x){ alert(x); }
var myscope = {
label : "myscope (toplevel)",
func1 : function() {
say("enter func1");
var label = "inner func1";
say(" this.label: " + this.label);
say(" label: " + label);
},
func2 : function() {
var label = "inner func2";
say("enter func2");
this.func1();
}
};
myscope.func2();
如果你运行它,它会表现得很好,并且对 this.xxx
的引用都会如你所愿地成功。但是,如果您像这样添加 func3:
func3 : function() {
setTimeout( function(){
var label = "anonymous func";
say("enter anon func");
this.func1();
}, 2);
}
...它不会像您想象的那样工作。因为匿名函数没有在明确指定的范围内定义,所以其中的 this
引用顶级对象 window
。并且没有 func1
作为窗口的子项(没有名为 func1
的顶级对象)。
出于同样的原因,您在调用 bind()
时使用的匿名函数中的 this
将失败。在那种情况下,您可以直接引用“命名空间”对象,或者您可以使用闭包(有些人称之为“that
trick”):
bindMethodsToNavigation: function() {
var that = this;
$("#subnavigation a").bind('click', function(event) {
var chosenLink = event.target;
that.removeClassFromSubNav();
that.loadPartial(chosenLink);
that.addChosenClassToNav(chosenLink);
return false;
});
}
bindMethodsToNavigation
范围内的this
指的是newAndImproved
。匿名函数中的 this
将引用 window
。使用闭包可以让你引用你想要的东西。 (编辑评论:我个人觉得 that
这个名字很可爱,完全没有帮助。我喜欢使用缩写名称,在你的情况下可能像 nai
来引用 newAndImproved
)
顺便说一句,你也可以这样做:
clickHandler : function(event) {
var chosenLink = event.target;
this.removeClassFromSubNav();
this.loadPartial(chosenLink);
this.addChosenClassToNav(chosenLink);
return false;
},
bindMethodsToNavigation: function() {
$("#subnavigation a").bind('click', clickHandler);
},
...如果它们都是 newAndImproved
对象的成员,那么 clickHandler
中的 this
将被解析为 newAndImproved
对象。这里的关键是 clickHandler
不是匿名的顶级函数;它属于 newAndImproved
,当在其中使用 this
时,它会正确解析。更重要的是,您可以在 clickHandler
中放弃使用 this
;这没有错,但没有必要。有些人喜欢添加它以强调那些稍后可能会阅读代码的人。
编辑
关于此的更多说明 - 关于是使用匿名函数还是命名函数作为事件处理程序的决定...... Anon 函数非常方便和简单,每个人都使用它们。我发现,在 Firebug 或 IE Javascript 调试器中,当我查看堆栈跟踪时,我得到了一个很长的匿名函数列表,而且很难弄清楚函数链是什么。特别是 AJAX 和异步处理程序被触发以响应 UI 事件等。为了在调试时提供一些额外的可见性,我有时会使用命名函数(放入命名空间),并且调用堆栈将显示一些命名的 fns 以及穿插一些匿名 fns。这有时会有所帮助。 不过,这只是一件小事。
关于javascript - 当我将 jquery dom 操作方法放入命名空间时,"this"没有按预期解析?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5938108/