"这个"预期,当我把我的jQuery的DOM操作方法的namepsace不能解决?

Fin*_*nnn 4 javascript jquery namespaces

我设法避免在我的大多数javascript dev中使用命名空间到目前为止,但我开始通过阅读像这样的有用文章看到光

我正在按照此处的 Maeagers技术创建我的命名空间,如下所示 -

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;
    });
}

};
Run Code Online (Sandbox Code Playgroud)

我把这个命名空间称为 -

$(document).ready(function() {
newAndImproved.targetDiv = $("#subcontent");
newAndImproved.loadInitialPage();
newAndImproved.bindMethodsToNavigation();
});
Run Code Online (Sandbox Code Playgroud)

我确定你已经注意到我在自己内部引用命名空间而不仅仅是使用'this'.我认为这是不正确的.但是当我使用'this'时,绑定部分将不起作用.

奇怪的是,loadInitialPage方法在使用'this'时会起作用.

知道我做错了什么吗?

提前致谢.

Che*_*eso 6

你需要使用这个that技巧. this在新范围内重新分配,包括您绑定的匿名函数.

考虑以下代码:

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();
Run Code Online (Sandbox Code Playgroud)

如果你运行它,它会表现得很好,并且this.xxx所有引用都可以按你的意愿成功.但是,如果你添加这样的func3:

    func3 : function() {
        setTimeout( function(){
            var label = "anonymous func";
            say("enter anon func");
            this.func1();
        }, 2);
    }
Run Code Online (Sandbox Code Playgroud)

......它不会像你想象的那样奏效.因为匿名函数是在没有明确指定的范围this内定义的,所以它内部引用了顶级对象window.而且没有func1窗口的孩子(没有命名的顶级对象func1).

出于同样的原因,this您在调用中使用的函数内部bind()将失败.在这种情况下,您可以直接引用"namespace"对象,或者您可以使用闭包(有些人称之为" that技巧"):

    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;
        });
    }
Run Code Online (Sandbox Code Playgroud)

所述this的范围内bindMethodsToNavigation是指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);
    },
Run Code Online (Sandbox Code Playgroud)

...如果它们都是newAndImproved对象的成员,那么this内部clickHandler将被解析为newAndImproved对象.这里的关键是它clickHandler不是一个匿名的顶级函数; 它属于它,newAndImprovedthis它在其中使用时,它会适当地解析.更重要的是,你可以放弃使用this内部clickHandler; 这不是不正确的,但这是不必要的.有些人喜欢将它添加到那些可能稍后阅读代码的人身上.


编辑

关于这一点的另一个注意事项 - 关于是否使用匿名函数或命名函数作为事件处理程序的决定... Anon函数是如此方便和容易,并且每个人都使用它们.我发现在Firebug或IE Javascript调试器中,当我查看堆栈跟踪时,我得到了一个非常功能的loooong列表,并且很难弄清楚函数链是什么.特别是AJAX和异步处理程序在响应UI事件时被触发,等等.为了在调试时提供一些额外的可见性,我有时使用命名函数(放入命名空间),并且callstack将显示一些名为fns,其中散布着一些anon fns.这有时会有所帮助 但是,这只是一件小事.