3

I'm trying to write more structured / object-oriented JS, as opposed to my old trusted "jQuery spaghetti" approach. Below I have a bit of JS to create multiple widgets on a page, and each widget has a "close" and "favorite" button.

My question is twofold:

1) Let's say we have 10-20 items/widgets on the page/dom (with a class of "item") that we want to apply JS functionality to. Is there a better way of creating a new instance of our "Item" class for each element than how I'm doing this at the very bottom of the code below?

2) Is there another way of accessing an object's properties and methods while inside a method? For example, something like "this.methodName" works in some instances, but in other instances the context of "this" will not be the object, so I'm not sure how to access things.

You'll see in my "events" method I use ".bind(this)" to alter the context of "this" so I can access object properties once I'm in the "close" or "favorite" methods. I'm thinking this use of "bind" isn't the best approach here - is there a more consistent / clean way of accessing object properties & methods without micromanaging "this" context?

var Item = function(el) {
    // define variables we will need
    this.elem = el;
    this.closeButton = el.find(".close");
    this.favoriteButton = el.find(".favorite");

  // run ui event listeners when instance is created
    this.events();
};

// ui event listeners - call appropriate method
Item.prototype.events = function() {
    this.closeButton.on("click", this.close.bind(this));
    this.favoriteButton.on("click", this.favorite.bind(this));
};

// close method
Item.prototype.close = function() {
    this.elem.remove();
};

// favorite method
Item.prototype.favorite = function() {
    this.favoriteButton.remove();
    this.elem.append("Favorited!")
};

/* all elements with a class of item should
 receive our Item class features */
$(".item").each(function() {
    new Item($(this));
});

Basically, I'm wondering how to write well structured OO JS while interacting with multiple DOM elements. I've seen a lot of great "module pattern" guides online but a lot of these follow the "singleton" approach. Or I might just be misunderstanding everything :)

Any help is appreciated!

Not sure if this is helpful or not: but here is a JSFiddle of this example - I know we shouldn't rely on JSFiddle links for questions or answers because they aren't useful for SO archiving purposes, but I have the JS above for reference, hopefully this fiddle is just a bonus help.

BlueCode
  • 57
  • 6

1 Answers1

0

My thoughts

  1. At the end of the day you have to register event handlers to dom elements so I think creating a new object for everything in your model is a good solution. Your code is clear which event handlers are registered for which parent item.

  2. The way this is resolved at runtime is covered really well in this S.O. question. Basically the jquery event handling mechanism is ultimately what is calling the handler you are associating and therefore it has a lot of control over what the this keyword is. However you can hand the handler a function that you bind the this arg explicitly. You are already doing this in your example and it shouldn't let you down. I would be interested in seeing an example where this doesn't work.


var obj = {x: 'hello world'};
$('#btn').on('click', (function () {
    console.log(this.x);
}).bind(obj));
Community
  • 1
  • 1
t3dodson
  • 3,949
  • 2
  • 29
  • 40
  • Thanks! That S.O. answer about "this" - looks like great studying material. Here's a related question: when I'm creating the new instance for each ".item" element at the bottom of my code, is it typical to create new instances in this way that aren't saved to a specific variable/object (instead of item3 = new Item())? Just wondering if there was an industry standard way of handling that... I'm new to OO and am having a hard time wrapping my head around interacting with the DOM in an organized fashion (most guides I've seen are about manipulating native JS datatypes, not touching the dom :) ) – BlueCode Jan 03 '16 at 04:41
  • Honestly most people do what you are trying to avoid "JQuery Spaghetti". So you are doing better than most. The spaghetti is close to standard because it is so common. I think your OO example is a nice solution and gets a lot of reuse. The pattern you are using `new Item(el);` is fine you don't need to keep around references to the objects if they aren't useful to you. Nothing bad will happen. – t3dodson Jan 03 '16 at 04:55