4
\$\begingroup\$

In the process of teaching myself JavaScript. Starting to branch off into OOP designs and did not want to continue until I knew I was doing it correctly.

Is this a common or accepted way of formatting an object in JavaScript, along with its constructor and methods? I have seen many different ways of doing this (at least it seems like it). Any other irregularities that could be brought to my attention would also be nice.

function Person(firstName, lastName, age){
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
}

Person.prototype = {
  fullName:function(){
    return this.firstName + " " + this.lastName;
  },

  changeFirstName:function(name){
    this.firstName = name;
  },

  changeLastName:function(name){
    this.lastName = name;
  },

  changeAge:function(age){
    this.age = age;
  },

  displayInfo:function(){
    document.write("Fullname: " + this.fullName() + "<br />");
    document.write("Age: " + this.age + "<br />");
  }
}

// Was just testing the functions.
var person = new Person("first", "last", 20);
document.write(person.fullName() + "<br />");
person.changeFirstName("FIRST");
document.write(person.fullName() + "<br />");
person.displayInfo();
\$\endgroup\$
7
\$\begingroup\$

There a few techniques to write a class in JavaScript, and each has its strengths and weaknesses. The prototypical technique you use is fine, but there are a few things you should note:

Overwriting the prototype as opposed extending it

Like Joseph said, when you assign Person.prototype = {, you are overwriting the original prototype which can result in some lost properties. If you rely on the constructor property of a class, this will not be accessible once you've overwritten the prototype. To keep the constructor property, you could add it to your custom prototype:

Person.prototype = {
  constructor: Person,
  fullName: function () {
    return this.firstName + " " + this.lastName;
  },
  //...
}

For more info on the subject, these two Stack Overflow questions go into more detail: Overwriting Prototype Bad Practice, Using Prototype Best Practice.

Public Mutable Data

When you use this.firstName = firstName, you give a user of a person object full access to that data member; they can directly modify it with person.firstName = "newName". This is true for all the data members of your Person class which makes your changeX functions obsolete.

If you want the data in the Person class to be private, there's another technique for making classes that utilizes closures:

function createPerson(firstName, lastName, age) {
  return {
    getFirstName: function () {
      return firstName;
    },
    getLastName: function () {
      return lastName;
    },
    getAge: function () {
      return age;
    },
  };
}

A downside to this technique is that you create separate functions for each instance of the class instead of each instance sharing the functions in the prototype.

Cohesion

The function displayInfo feels out of place in your function class. As a general practice, it's more clear to have each class/function/module perform one specific task. Your person class appears to do two things: manage the data for a person AND display it's data to an html document. One downside to less cohesive code is that it can create dependencies that probably shouldn't be there. For example, your Person class depends on the document object which wouldn't be available in a node.js setting. You might consider breaking out displayInfo into it's own function:

function displayPersonInfo(person) {
  document.write("Fullname: " + person.fullName() + "<br />");
  document.write("Age: " + person.age + "<br />");
}
|improve this answer|||||
\$\endgroup\$
7
\$\begingroup\$

This is the original way to write near-classical OOP in JavaScript and everything appears to be correct. However, there is one quirk you should know of when doing it this way.

By default, a function's prototype property is an object that has a property called constructor. By default, this points back to the function. However, if you define the prototype as Constructor.prototype = {}, you are overriding the object with a new object, essentially throwing away the old object containing constructor. While in most cases you will not use this property, it often comes handy.

An alternative way, instead of assigning a new object to the function's prototype object is to just add properties to it.

Person.prototype.fullName = function(){...}
Person.prototype.changeFirstName = function(){...}

Now for this piece of code:

displayInfo:function(){
  document.write("Fullname: " + person.fullName() + "<br />");
  document.write("Age: " + this.age + "<br />");
}

Use document.write is highly discouraged unless you know what you are doing. When you call document.write, it implicitly calls document.open which clears the page, erasing everything on it, before writing. Use DOM operations like innerHTML on an element or console functions to avoid wiping off the page when writing your outputs.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ When adding properties to a function like this alternative way suggests, is there a way to group these properties within their own block so that they are better organized or better associated with the function? I remember seeing this format but kinda leaned towards the method I used because each function was grouped together like I am generally use too. \$\endgroup\$ – JSextonn Jul 30 '16 at 22:15
  • \$\begingroup\$ @Leon you are not adding them to the function, but the functions prototype object. The prototype object is exactly the grouping you are looking for. This is the closest you can get to associating functions to a "class" in JavaScript like other languages do it. You can add an object to the prototype, but there's no real point in doing so. \$\endgroup\$ – I'll add comments tomorrow Jul 30 '16 at 23:24
  • \$\begingroup\$ @leon you could also look into the es6 class syntax \$\endgroup\$ – Joshua Dawson Jul 31 '16 at 1:06
  • \$\begingroup\$ @Josh Dawson Wow yea, ES6 is amazing. It even comes with some other pretty useful tools. Thanks for the recommendation. \$\endgroup\$ – JSextonn Jul 31 '16 at 9:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for?Browse other questions tagged or ask your own question.