Applying OOP with jQuery

2019-04-07 13:15发布

I'm working with jQuery and trying to apply some basic Javascript OOP principles to a set of functions that control hover behavior. However, I can't figure out how to get the "this" keyword to refer to the instance of the object I'm creating. My sample code is:

var zoomin = new Object();

zoomin = function() {
       // Constructor goes here
};

zoomin.prototype = {
       hoverOn: function() {
          this.hoverReset();
          // More logic here using jQuery's $(this)...
       },
       hoverReset: function() {
          // Some logic here.
       }
       };

// Create new instance of zoomin and apply event handler to matching classes.
var my_zoomin = new zoomin();
$(".some_class").hover(my_zoomin.hoverOn, function() { return null; });

The problematic line in the above code is the call to "this.hoverReset()" inside the hoverOn() function. Since "this" now refers to element that was hovered on, it does not work as intended. I would basically like to call the function hoverReset() for that instance of the object (my_zoomin).

Is there any way to do this?

Thanks!

3条回答
冷血范
2楼-- · 2019-04-07 13:56

Only assigning a function to a property of an object does not associated this inside the function with the object. It is the way how you call the function.

By calling

.hover(my_zoomin.hoverOn,...)

you are only passing the function. It will not "remember" to which object it belonged. What you can do is to pass an anonymous function and call hoverOn inside:

.hover(function(){ my_zoomin.hoverOn(); },...)

This will make the this inside hoverOn refer to my_zoomin. So the call to this.hoverReset() will work. However, inside hoverOn, you will not have a reference to the jQuery object created by the selector.

One solution would be to pass the selected elements as parameter:

var zoomin = function() {
   // Constructor goes here
};

zoomin.prototype = {
   hoverOn: function($ele) {
      this.hoverReset($ele);
      // More logic here using jQuery's $ele...
   },
   hoverReset: function($ele) {
      // Some logic here.
   }
};


var my_zoomin = new zoomin();
$(".some_class").hover(function() { 
    my_zoomin.hoverOn($(this));  // pass $(this) to the method
}, function() { 
    return null; 
});

As a next step, you could consider making a jQuery plugin.

查看更多
Bombasti
3楼-- · 2019-04-07 14:04

please see my answers to these questions:

where is my "this"?

why is "this" not this?

this confusion comes up all the time.

when you pass a function in as a callback, it's invoked as a standalone function, so its "this" becomes the global object.

"bind" is a native part of ecmascript 5, and is part of the function prototype. If you go to the end of my second answer up there, you get a link to the mozilla website, which has a "compatibility" version of the bind function. Use use myfunction.bind(myobject), and it'll use the native function if it's available, or the JS function if it is not.

查看更多
何必那么认真
4楼-- · 2019-04-07 14:09
  1. You can "bind" the event handler to the object (see Mootools bind code for example).
  2. You can pass the object as a parameter in the anonymous function and use that instead of this in the event handler

As for 1, you add the bind method to function

bind: function(bind){
        var self = this,
            args = (arguments.length > 1) ? Array.slice(arguments, 1) : null;

        return function(){
            if (!args && !arguments.length) return self.call(bind);
            if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments)));
            return self.apply(bind, args || arguments);
        };
    }

Not sure though how well it will interact with JQ stuff.

查看更多
登录 后发表回答