user10364768
user10364768

Reputation: 143

Should we add methods only to the prototypes of our objects?

I'm currently studying Javascript and saw that we can define members of an object in its prototype instead of in the object's constructor since it makes the objects lighter because they don't carry the method code in every instance.

I can see how variables can work badly if all objects of this constructor point to the same variable field, but methods shouldn't change too much or at all, so its not a problem to share them.

Is there a reason not to define methods on the prototype rather than the object's constructor?

Upvotes: 0

Views: 170

Answers (2)

petkov.np
petkov.np

Reputation: 520

Just an idea from me - there is a way of dealing with the "proper" execution context of e.g. click handlers on prototype level as well. Consider the following example:

class AbstractClickHandler {
    
  // the "proper" this is ensured via closure over the actual implementation
  clickHandler() {
    return (...args) => {
      this.handleClick.apply(this, args)
    }
  }

  // no-op in base class
  handleClick() {   
  }
}

class ClickHandler extends AbstractClickHandler {

  constructor(data) {
    super()
    this.data = data
  }

  // actual implementation of the handler logic
  handleClick(arg1, arg2) {
    console.log(`Click handled with data ${this.data} and arguments ${arg1}, ${arg2}`)    
  }
}

const instance = new ClickHandler(42)
const handler = instance.clickHandler()
handler.call(null, 'one', 'two')

This way, there is no need to define a bound handler in every concerned constructor.

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370699

One reason why one might prefer putting methods on the instance itself would be to ensure the correct this context while adding a method concisely. Getting this to work properly is a very common problem in JavaScript.

For example:

class Foo {
  i = 0;
  clickHandler = () => console.log(this.i++);
}

const f = new Foo();
window.onclick = f.clickHandler;

This is a common pattern with class components in React. If one put the method on the prototype instead, it could sometimes get a bit uglier:

class Foo {
  i = 0;
  clickHandler() {
    console.log(this.i++);
  }
}

const f = new Foo();
window.onclick = () => f.clickHandler();

Another common way of dealing with this is to move a bound method from the prototype to the instance in the constructor:

class Foo {
  i = 0;
  constructor() {
    this.clickHandler = this.clickHandler.bind(this);
  }
  clickHandler() {
    console.log(this.i++);
  }
}

const f = new Foo();
window.onclick = () => f.clickHandler();

Is that reason to prefer one over the other? That's up to you, but its one arguable advantage to keep in mind.

Upvotes: 2

Related Questions