开发者

javascript: use of 'this' in object literal function giving an error

开发者 https://www.devze.com 2023-03-03 08:47 出处:网络
I\'m having to fix up a megamenu system for a site I\'ve been handed, and I\'ve run into a bug. Once the DOM is ready (jQuery is included) the megamenu\'s render function is run. Within this there a

I'm having to fix up a megamenu system for a site I've been handed, and I've run into a bug.

Once the DOM is ready (jQuery is included) the megamenu's render function is run. Within this there a listener is added for resize to rerun this function, re-rendering the code. However, I'm getting javascript errors that think that this render function when called from within the object is actually a function of the window so I get "Uncaught TypeError: Object [object DOMWindow] has no method 'render'".

But the function runs anyway!

here's a brief snapshot of the code:

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

    }

}

Now I've tried jkmegamenu.render($) (don't know what the dollar is for, works with or without due to jQuery I imagine), and I've tried defining self as self: this but the same error occurs. Its a fairly large file and I'm pretty busy so I'm only considering recodin开发者_如何学JAVAg it a proper jQuery object (e.g. http://www.phpied.com/3-ways-to-define-a-javascript-class/) if thats the only other option, otherwise does anyone know a quick fix?

The site is kent.ac.uk and you'll be able to see the errors popping up, especially on resize.


this in JavaScript is a bit different than you may be used to from some other languages like C++, C#, or Java. It's defined entirely by how a function is called, not where the function is defined. More here: You must remember this

In your case, if you want to ensure that this refers to your jkmegamenu instance, you could use jQuery's proxy function, which will create a closure for you behind-the-scenes that calls your function with the correct "context" (this value):

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

}

Or just use your own closure directly:

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

}

...which has the advantage that you can then use this to refer to the DOM object you hooked the event handler to (okay, so less useful for window, but quite useful when binding to other objects).

Closures are an extremely useful way of handling events. More here: Closures are not complicated

For your situation, since jkmegamenu is a singleton, I'd probably just use the module pattern and not worry about this at all:

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

That has the advantage of also giving your functions names, which helps your tools help you, and lets you have truly private functions as well.

You can also apply this pattern to factory functions ("classes" some would call them, although JavaScript doesn't have classes), with a bit of tweaking.


Javascript acts a little differently than you'd expect, in the sense that 'this' refers to whatever functional scope it is currently in. So 'this' does not point to what you'd expect. Instead, use:

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


Within your resize function, the this keyword refers to the DOM object being resized.

If you want to use the this object from the parent function, your best bet is to create a temporary variable pointing to this in the parent function. That variable will then be available in the scope of your resize function.

For more on how Javascript's this works, see this article: http://javascriptweblog.wordpress.com/2010/08/30/understanding-javascripts-this/

0

精彩评论

暂无评论...
验证码 换一张
取 消