我不得不为我已经交过的网站修建一个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,你将能够看到弹出的错误,特别是在调整大小时.
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没有类),稍微调整一下.