Manel R. Doménech
Manel R. Doménech

Reputation: 173

Object.create inheritance and initialization code

I have the following code that defines a class for input events management: mouse, touch, pointer, ...

// base.js
export default () => {
  return {
    el: undefined,
    event: undefined,
    handler(ev) {
      console.log('default handler')
    },
    attach() {
      el.addEventListener(event, this.handler.bind(this), false)
    },
    detach() {
      el.removeEventListener(event, this.handler.bind(this), false)
    }
  }
}

// mouse.js
import baseInput from './base'

export default (el) => {
  return Object.assign(Object.create(baseInput()), {
    el: undefined,
    event: 'mousedown',
    handler(ev) {
      console.log('mouse handler)
    }
  }
}

There's some common business logic in 'base' object.

The problem comes from the calls to this.handler.bind(this) in attach and detach functions, because the returned bound function is not the same for each call, so removeEventListener can't remove the event listener added by addEventListener.

I know I have to keep one single function reference. My question is where that code should be.

One solution may be:

// base.js
export default () => {

  let boundFunction;

  return {
    el: undefined,
    event: undefined,
    getBoundFunction() {
      if (!boundFunction) {
        boundFunction = this.handler.bind(this)
      }
    },
    handler(ev) {
      console.log('default handler')
    },
    attach() {
      el.addEventListener(event, this.getBoundFunction(), false)
    },
    detach() {
      el.removeEventListener(event, this.getBoundFunction(), false)
    }
  }
}

This code works, but I don't want that extra getBoundFunction call for each event triggered and I think there should be a better method or best practice.

Upvotes: 0

Views: 53

Answers (1)

llama
llama

Reputation: 2537

Implement the event listener interface by changing the name of handler to handleEvent. Then you just bind the object directly.

The value of this in the handleEvent function will be the bound object.

// base.js
export default () => {
  return {
    el: undefined,
    event: undefined,
    handleEvent(ev) {
      console.log('default handler')
    },
    attach() {
      el.addEventListener(event, this, false)
    },
    detach() {
      el.removeEventListener(event, this, false)
    }
  }
}

So then objects that inherit from the base object can define their own handleEvent function, which will get called when the bound events fire.


Also, you seem to be creating a new base object for each object that inherits from it. Why not share a base object? That's the point of prototypal inheritance.

Upvotes: 3

Related Questions