简体   繁体   中英

Regarding the fallback constructor function pattern in JavaScript?

I was tested on my knowledge on creating functions which would be called as a constructors in JavaScript.

function Clonetrooper(name, rank, age) {
  this.name = name;
  this.rank = rank;
  this.age = age;

I have gotten into a practice of using this line of code

  if (!(this instanceof Clonetrooper)) return new Clonetrooper();
}

to prevent the function from being called without the new keyword.

The teacher/grader noted the following comment.

This isn't necessary and actually isn't doing what you would want it to do. This will set properties on 'this' and then return a completely separate instance of Clonetrooper without those properties set.

To be fair I did forgot to add the props like so...

if (!(this instanceof Clonetrooper)) return new Clonetrooper(name, rank, age);

But actually turns out that doesn't matter...

Doing it like this, (like in the original code)

  if (!(this instanceof Clonetrooper)) return new Clonetrooper();

will return an object with those properties—only they hold the value undefined

new Clonetrooper
Clonetrooper {name: undefined, rank: undefined, age: undefined}

So can someone explain what they meant?

while invoking return new Clonetrooper(); , you are not passing any argument, but it expects 3 arguments, resulting the call of Clonetrooper with these name, rank, age are undefined, so by execution of

  this.name = name;
  this.rank = rank;
  this.age = age;

those attributes are set to undefined in the newly created object, thats why you are getting

{name: undefined, rank: undefined, age: undefined}

This will set properties on 'this' and then return

Is the major issue. You must not run all the property initialisation code and then in the end decide to actually create a proper new instance, you need to bail out in the very beginning.

a completely separate instance of Clonetrooper without those properties set.

…to the argument values, they meant.


Btw, in modern ES6 you'd write

function Clonetrooper(name, rank, age) {
  if (!new.target) return new Clonetrooper(...arguments);
  this.name = name;
  this.rank = rank;
  this.age = age;
}

or just use class syntax right away.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM