javascript:在对象文字函数中使用'this'给出错误

red*_*oot 3 javascript

我不得不为我已经交过的网站修建一个megamenu系统,而且我遇到了一个bug.

一旦DOM准备就绪(包含jQuery),就会运行megamenu的渲染功能.在其中添加了一个监听器,用于调整大小以重新运行此函数,重新呈现代码.但是,我得到的javascript错误认为,当从对象内部调用时,这个渲染函数实际上是窗口的一个函数,所以我得到"Uncaught TypeError:Object [object DOMWindow]没有方法'render'".

但无论如何功能都在运行!

这是代码的简短快照:

var jkmegamenu=
{
 ...
    render:function($)
    {
    ...
        $(window).bind("resize", function()
        {
          this.render($);
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

现在我已经尝试过jkmegamenu.render($)(不知道美元的用途是什么,无论是否因为我想象的jQuery而工作),我已经尝试将self定义为self:这个但是同样的错误发生了.它是一个相当大的文件,我很忙,所以我只考虑将它重新编码为一个合适的jQuery对象(例如http://www.phpied.com/3-ways-to-define-a-javascript-class/)如果这是唯一的其他选择,否则有人知道快速修复吗?

该网站是kent.ac.uk,你将能够看到弹出的错误,特别是在调整大小时.

T.J*_*der 5

this在JavaScript中,您可能习惯于使用其他语言,如C++,C#或Java.它完全由函数的调用方式定义,而不是函数的定义.更多信息:你必须记住this

在您的情况下,如果您想确保this引用您的jkmegamenu实例,您可以使用jQuery的proxy函数,它将为您创建一个闭包,在幕后使用正确的"上下文"(this值)调用您的函数:

var jkmegamenu=
{
 ...
    render:function($)
    {
    ...
        $(window).bind("resize", $.proxy(function()
        {
          this.render($);
        }, this));
    }

}
Run Code Online (Sandbox Code Playgroud)

或者直接使用你自己的闭包:

var jkmegamenu=
{
 ...
    render:function($)
    {
    ...
        var inst = this; // Remember `this`
        $(window).bind("resize", function()
        {
          // Use it
          inst.render($);
        });
    }

}
Run Code Online (Sandbox Code Playgroud)

...它的优势在于你可以使用它this来引用你挂钩事件处理程序的DOM对象(好吧,所以不那么有用window,但在绑定到其他对象时非常有用).

闭包是处理事件的一种非常有用的方法.更多信息:闭包并不复杂

对于你的情况,既然jkmegamenu是单身,我可能只是使用模块模式而不用担心this:

var jkmegamenu = (function() {
    var inst = {};

    // ...

    inst.render = jkmegamenu_render;
    function jkmegamenu_render($)
    {
        $(window).bind("resize", function()
        {
          inst.render($);
          // Or just jkmegamenu_render($);
        });
    }

    // Could have some private functions here, just by
    // virtue of not adding them to `inst`

    // ...

    return inst;
})();
Run Code Online (Sandbox Code Playgroud)

这样做的好处是还可以提供功能名称,这有助于您的工具为您提供帮助,并让您拥有真正的私人功能.

您也可以将此模式应用于工厂函数(有些人会称之为"类",尽管JavaScript没有类),稍微调整一下.