“这个”当我将 jquery dom 操作方法放入命名空间时,未按预期解析?

发布于 2024-11-06 03:19:19 字数 1792 浏览 0 评论 0原文

迄今为止,我已经设法避免在大多数 javascript 开发中使用名称空间,但通过阅读 这个

我正在遵循 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;
    });
}

};

我已经这样称呼该命名空间 -

$(document).ready(function() {
newAndImproved.targetDiv = $("#subcontent");
newAndImproved.loadInitialPage();
newAndImproved.bindMethodsToNavigation();
});

我确信您已经注意到我在其内部引用命名空间,而不仅仅是使用“this”。我认为这是不正确的。但是当我使用“this”时,绑定部分将不起作用。

奇怪的是,当使用“this”时,loadInitialPage 方法将起作用。

知道我做错了什么吗?

提前致谢。

I've managed to avoid using namespace in most of my javascript dev to date, but I'm beginning to see the light through reading helpful articles like this one

I'm following Maeagers technique found here to create my namespace as shown below -

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

};

I've called that namespace like this -

$(document).ready(function() {
newAndImproved.targetDiv = $("#subcontent");
newAndImproved.loadInitialPage();
newAndImproved.bindMethodsToNavigation();
});

I'm sure you've noticed that I'm referencing the namespace within itself rather than just using 'this'. I assume this is incorrect. But when I use 'this' the binding part will not work.

Strangely, the loadInitialPage method will work when using 'this'.

Any idea what I'm doing wrong?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

怪我太投入 2024-11-13 03:19:19

您需要使用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();

如果您运行此代码,它将表现良好,并且对 this.xxx 的引用都会如您所愿地成功。但是,如果您添加这样的 func3:

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

...它将不会像您想象的那样工作。由于匿名函数没有明确指定的作用域中定义,因此其中的 this 引用顶级对象 window。并且没有 func1 作为 window 的子级(没有名为 func1 的顶级对象)。

出于同样的原因,您在调用 bind() 时使用的匿名函数中的 this 将失败。在这种情况下,您可以直接引用“命名空间”对象,也可以使用闭包(有些人称之为“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;
        });
    }

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

...如果它们都是 newAndImproved 对象的成员,则 this< clickHandler 中的 /code> 将解析为 newAndImproved 对象。这里的关键是 clickHandler 不是一个匿名的顶级函数;而是一个匿名函数。它属于 newAndImproved ,当在其中使用 this 时,它会正确解析。更重要的是,您可以在 clickHandler 中删除 this 的使用;这并不是不正确,但没有必要。有些人喜欢添加它以强调那些稍后可能会阅读代码的人。


编辑

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

You need to use the that trick. this gets re-assigned inside new scopes, including the anonymous function you are binding.

Consider this code:

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

If you run this, it will behave nicely, and the references to this.xxx all succeed as you would like. However, if you add a func3 like this:

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

...it will not work as you might imagine. Because the anonymous function is defined in no explicitly-specified scope, the this within it refers to the top level object, window. And there is no func1 as a child of window (no top level object named func1).

For the same reason, the this within your anon function that you use in the call to bind() will fail. In that case you can refer to the "namespace" object directly, or you can use a closure (some people call it "the 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;
        });
    }

The this within the scope of bindMethodsToNavigation refers to newAndImproved. The this within the anonymous function will refer to window. Using a closure allows you to refer to the thing you want. (editorial comment: I personally find the name that to be cute and entirely unhelpful. I like to use abbreviated names, in your case maybe something like nai to refer to newAndImproved)

Incidentally, you could also do this:

    clickHandler : function(event) {
        var chosenLink = event.target;
        this.removeClassFromSubNav();
        this.loadPartial(chosenLink);
        this.addChosenClassToNav(chosenLink);
        return false;
    },

    bindMethodsToNavigation: function() {
        $("#subnavigation a").bind('click', clickHandler);
    },

...and if they are both members of the newAndImproved object, then the this within clickHandler will be resolved to the newAndImproved object. The key here is that clickHandler is not an anonymous, top-level function; it belongs to newAndImproved and when this is used within it, it resolves appropriately. Even more, you can just drop the use of this within clickHandler; it is not incorrect, but it is unnecessary. Some people like to add it for emphasis to those who might read the code later.


EDIT

One more note on this - on the decision whether to use anonymous functions or named functions as event handlers... Anon functions are so convenient and easy, and everybody uses them. What I find is that in Firebug or the IE Javascript Debugger, when I look at a stack trace I get a loooong list of anon functions, and it's difficult to figure out just what the chain of functions is. Especially with AJAX and async handlers being fired in response to UI events, and so on. To provide some additional visibility at debug time, I sometimes use named functions (put into namespaces), and the callstack will show a few named fns along interspersed with a few anon fns. This sometimes helps.
Just a small thing, though.

凌乱心跳 2024-11-13 03:19:19

我根本不认为需要命名空间。这看起来像是一个非常具体的实现(而不是可重用的类)。这不是更简单吗:

$(document).ready(function() {
    var targetDiv = $("#subcontent"),
    loadInitialPage = function() {
        ...
    },
    loadPartial = function(clickedLink) {
        ...
    },
    removeClassFromSubNav: function() {
        ...
    },
    addChosenClassToNav = function(chosenLink) {
        ...
    },
    bindMethodsToNavigation = function() {
        ...
    };

    loadInitialPage();
    bindMethodsToNavigation();
});

更简单,因为您现在可以引用所有没有命名空间的函数。不需要 this.namespacename.

为什么要将命名空间/函数声明与 document.ready 内容分开?

编辑
你应该读一下这篇文章。 它不止几行,但非常可读并且非常有用。

编辑
可以在 document.ready 中放入很多内容,因为它只执行一次。

I don't see the need for namespaces at all. This looks like a very specific implementation (and not a reusable class). Wouldn't this be much simpler:

$(document).ready(function() {
    var targetDiv = $("#subcontent"),
    loadInitialPage = function() {
        ...
    },
    loadPartial = function(clickedLink) {
        ...
    },
    removeClassFromSubNav: function() {
        ...
    },
    addChosenClassToNav = function(chosenLink) {
        ...
    },
    bindMethodsToNavigation = function() {
        ...
    };

    loadInitialPage();
    bindMethodsToNavigation();
});

Simpler because you can reference all functions without namespace now. No need for this. or namespacename..

Why separate the namespace/function declarations from the document.ready stuff?

edit
You should read this. It's more than a few lines, but it's very readable and very useful.

edit
It's alright to put a lot of stuff in document.ready, because that's only executed once.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文