javascript - 当我将 jquery dom 操作方法放入命名空间时,"this"没有按预期解析?

标签 javascript jquery namespaces

到目前为止,我已经设法避免在我的大部分 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/

相关文章:

javascript - 如何在 Plot 2 图表中以粗体显示轴标签

jQuery on() 不工作

javascript - 在 javascript 中作为数组成员存储的函数/命令

r - 我应该如何引用导入包中的函数?

javascript - 在与 mongoDb 和 mongoose 聚合后填充单个 ObjectId 引用

javascript - 旋转并保持 Font Awesome 图标的位置

javascript - 数字/字符串到只有数字

javascript - 单击与 Javascript 具有相同类名的类按钮

.net - XML 注释——您如何(或在哪里)为您的命名空间和库创建 XML 注释?

c++ - 为什么 C++ 友元类只需要在其他命名空间中进行前向声明?