0

In the constructor function below I didn't declare a new variable for each property. Instead I used the this keyword for each property. For example I didn't declare var species; up top but instead used this.species inside the function. This works in chrome and it saved me from having to declare a bunch of variables. But is there an obvious reason that I shouldn't create constructor function properties in this way? Is it considered sloppy or would it be generally frowned upon in the industry?

'use strict';
 
var zombie;
 
const Creature = function() {
  this.species = null;
  this.action = null;
  this.story = function() {
    console.log("The " +this.species +" is about to " +this.action +".");
  }
}
 
zombie = new Creature();
 
zombie.species = "zombie";
zombie.action = "strike";
 
zombie.story();
DR01D
  • 1,245
  • 9
  • 21
  • 6
    That is the correct way of doing things. Local variables declared in the constructor function do **not** become properties of the constructed object. – Pointy Nov 01 '17 at 17:26
  • 1
    This is perfectly normal. If you're assigning the value 'null' though, I would recommend using jsdoc to document what type you expect it to be. – TKoL Nov 01 '17 at 17:29
  • 1
    Also, setting props to null is not necessary. – dhilt Nov 01 '17 at 17:29
  • You should use the constructor to pass in construction time variables. This makes your IDE much friendlier when other people are using your code. – bryan60 Nov 01 '17 at 17:31

3 Answers3

1

Not only is that okay, it's the right way to do it. Declaring variables in your constructor just makes them variables in the constructor, it doesn't make them properties of the instance. What you're doing does make them properties, and is correct (and well-supported by IDE code-completion; e.g., later if you type zombie. the IDE knows that zombie probably has species, action, and story, and can auto-suggest them).


Somewhat tangential, but unless you have a good reason for creating a separate story function for each instance, put it on the object that will be assigned as the new object's prototype instead:

const Creature = function() {
  this.species = null;
  this.action = null;
};
Creature.prototype.story = function() {
  console.log("The " +this.species +" is about to " +this.action +".");
};

If you're using constructor functions, as you're already using ES2015+ features (const), you might consider using class:

class Creature {
  constructor() {
    this.species = null;
    this.action = null;
  }
  story() {
    console.log("The " +this.species +" is about to " +this.action +".");
  }
}

...as it's a bit more concise and declarative. Also, it prevents your calling Creature without new by mistake.


Separately, rather than

zombie = new Creature();
zombie.species = "zombie";
zombie.action = "strike";

...you might initialize those properties in the constructor:

class Creature {
  constructor(species, action) {
    this.species = species;
    this.action = action;
  }
  story() {
    console.log("The " +this.species +" is about to " +this.action +".");
  }
}

Then:

zombie = new Creature("zombie", "strike");

(Community wiki because this is largely what the comments on the question say, just expanded a bit.)

T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
1

you should make use of the constructor to pass in those values rather than doing it after:

'use strict';

var zombie;

const Creature = function(species, action) {
  this.species = species;
  this.action = action;
  this.story = function() {
    console.log("The " +this.species +" is about to " +this.action +".");
  }
}

zombie = new Creature("zombie", "strike");

zombie.story();

The reason is so when other people use your class, the IDE will give explicit instructions or show warnings if they're misusing it. If working in teams or producing code to be used by others, it's a requirement that your class usage be well defined and clear. This example is clearly contrived, but the story() function usage seems to expect that both those properties be set, so it should be required on construction.

bryan60
  • 22,247
  • 3
  • 31
  • 47
  • This is true, but it isn't an answer to the question that was asked. – T.J. Crowder Nov 01 '17 at 17:37
  • I interpreted his question differently than you. I think he was asking if he should pass properties as constructor arguments or set them manually? Otherwise I don't get the question, variables declared in a constructor don't do anything. – bryan60 Nov 01 '17 at 17:39
0

You have to be careful referencing 'this'. While you know what 'this' is in the constructor do you know what it is in a method of the object? How about when that method is called outside of your object? In ecmascript5 I always create a member 'self' in the closure of the object and assign this to self in the constructor. That way I always know what self refers to in my other methods. e.g.

  const Creature = function(species, action) {
    var self = this;
    self.species = species;
    self.action = action;

    self.story = function() {
      console.log("The " +self.species +" is about to " +self.action +".");
    }
  }

See this answer for how this works in javascript How does the "this" keyword work?

The punch line is that 'this' is bound to the scope of the caller. As such it does not always mean the containing instance of the object as it does in Java.

bhspencer
  • 11,362
  • 4
  • 29
  • 38