0

Let's say I have this code:

const MyObject = {
    a($els) {
        // What is the best practice here ?
        $els.each(function() {
            MyObject.b($(this));
        });
        // Or
        const self = this;
        $els.each(function() {
            self.b($(this));
        });
    },
    b($el) {
        $el.addClass('test');
    }
};

What is the "best practice" for calling another method in the object? Is there any downside calling the variable "MyObject"? Or is it better to use this and why?

Lord Grosse Jeanine
  • 1,111
  • 10
  • 29
  • 3
    What if you rename `MyObject` to something else in future? If you go with first approach, you'll have to make changes at two places. – 31piy Aug 01 '18 at 08:16
  • Well `this` would make it more re-usable.. – Keith Aug 01 '18 at 08:16
  • 1
    just use this.b(x) ? – Antti Aug 01 '18 at 08:18
  • Why `self = this`…?! – deceze Aug 01 '18 at 08:21
  • Looks a bit nonsensical: a(x) === b(x) here, so is there really a use case for this pattern? – KooiInc Aug 01 '18 at 08:23
  • @deceze I assume for when the function is larger, when its easy to loose object scope... – Keith Aug 01 '18 at 08:25
  • I edited the question so the use case is more clear. Sometime `this` gets replaced in loops or other logic stuff, and I end up with `const self = this;` at the begining of every function, that's why I was asking the best practice. – Lord Grosse Jeanine Aug 01 '18 at 08:30
  • That is something of a different problem: [How to access the correct `this` inside a callback?](https://stackoverflow.com/q/20279484/476) – deceze Aug 01 '18 at 08:40
  • @deceze that is/was a common work around for containing the scope of `this` before `=>` functions became widespread. Some polyfils will actually refactor `=>` into `var self = this;` for backwards compatibility (Babel does this for example) – Liam Aug 01 '18 at 09:25

3 Answers3

0

There is nothing wrong with

this.method(params)

however if you have nested scopes, this could mean different things and get confusing really fast. To avoid it, use var self = this to create another variable pointing towards the right this.

Example:

const MyObject = {
    a(x) {
        var self = this;
        return x.map(function (a) 
        {
           // cannot use this here to access parent scope
           return self.b(a);
        })


    },
    b(y) {
      return y % 2;
    }

};

Eriks Klotins
  • 4,042
  • 1
  • 12
  • 26
  • The more elegant solution for losing `this` would be `x.map(a => this.b(a))`… – deceze Aug 01 '18 at 08:27
  • I guess using `this` is indeed the best practice, but therefore I end up with `const self = this;` at the begning of most of my functions. This "code repetition" was the reason I asked ^^ – Lord Grosse Jeanine Aug 01 '18 at 08:37
0

You don't need jQuery. Without it the this problem can be avoided like this (pun intended;). If you really need jQuery, see the second part of the snippet for my take on it.

const MyObject = {
    getAll: selector => Array.from(document.querySelectorAll(selector)),
    addClass:  (elements, className) => 
      elements.forEach(element => element.classList.add(className)),
};

MyObject.addClass(MyObject.getAll("[data-test]"), "test");
setTimeout(() => 
  MyObject.addClass(MyObject.getAll("[data-test2]"), "test2"), 1000);
  
// using jQuery I'd use
const MyObjectJQ = {
  setClass4Elements($els) {
    const setClass = this.setClass2Foo;
    $els.each( (i, elem) => setClass($(elem)) );
  },
  setClass2Foo($el) {
    $el.addClass('foo');
  }
};

setTimeout(() => 
  MyObjectJQ.setClass4Elements($("[data-test2]")), 2000);

// still I'd avoid  the use of [this]
const MyObjectJQNoThis = {
  setClass4Elements($els, className) {
    const setClass = $el => $el.addClass(className);
    $els.each( (i, elem) => setClass($(elem)) );
  }
};

setTimeout(() => 
  MyObjectJQNoThis.setClass4Elements($("[data-test]"), "bar"), 3000);
.test {
  color: red;
}
.test2 {
  color: green;
}
.foo {
  color: orange;
}
.bar {
  color: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-test>div1</div>
<div data-test2>div2</div>
<div data-test>div3</div>
<div data-test2>div4</div>
KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • I used jQuery in the example because I am actually writing a jQuery plugin. But there are many non-jQuery cases in which `this` value can change (callbacks, loops). – Lord Grosse Jeanine Aug 01 '18 at 08:59
-3

I think you are confused about the difference between classes and objects. MyObject refers to the class of MyObject. The this keyword refers an the INSTANCE of the object. Im guessing you are wanting to accomplish the later, si the this keywod is what you want to use.