Page tree
Skip to end of metadata
Go to start of metadata

Given you use a constructor function to create a new Object, you can run into ugly side effects as soon as you forget the required `new` keyword.

 

Let's take an example:

 

function Zoo () {
  this.animals = ['cat', 'mouse', 'zebra']
}

const zp = new Zoo()
zp.animals // 'cat', 'mouse', 'zebra'

After creating a new instance of my Zoo Object, I can access the animals property with zp.animals.

What happens when we accidentally forget the `new` keyword?

const z = Zoo()
z.animals // undefined

Ouch! That can lead to weird behaviour in our applications and long debugging sessions.

 

With instanceof (even available in ES3) we can guard against it:

 

// constructor function guarded against accidental calling without new keyword
function EnhancedZoo () {
  if (!(this instanceof EnhancedZoo)) {
    return new EnhancedZoo()
  }
  
  this.animals = ['cat', 'mouse', 'zebra']
}

const ze = EnhancedZoo()
ze.animals // ['cat', 'mouse', 'zebra']

 

 

  • No labels

2 Comments

  1. This problem may cause very weird behavior indeed (without strict mode it will even create/override a global window.animals object) and using instanceof is probably a good way to battle such issues. Instead of silently correcting the code using return new Foo(), I'd prefer throwing an error, though, making it immediately clear to the developer, that he has used the constructor function wrong. As far as I know, that's also the behavior of ES6 classes (as you're using const, I assume you're using some sort of ES6→ES5 compiler like Babel/Traceur anyway).

    1. yep agreed! i also like to crash early and sometimes it depends on the use case. in this case it was an error object `throw new CustomError()`. going further we could definitely become more strict, recast could help to find and fix those.

      > I assume you're using some sort of ES6→ES5 compiler like Babel/Traceur anyway

      we are not transpiling yet in the cli