Search code examples
javascriptfunctionmethodsconstructor

Calling a javascript constructor functions method


I am having trouble calling a method inside of a constructor function I have made. Here is the function and my attempt to call it...

var Cohort = function(program, campus, number, students){
    this.program = program,
    this.campus = campus,
    this.number = number,
    this.students = students,
    function sayName(){
        return `This cohort is called ${program}, ${campus}, ${number}.`
    },
    function takeAttendance(){
        return console.log(students)
    }
}

var cohort1 = new Cohort("w", "pr", 27, ['devin', 'ben', 'bob'])
var cohort2 = new Cohort('w', 'pr', 31, ["Brendan Eich", "Dan Abramov", "Wes Bos", "Kent Dodds"])

cohort1.sayName()

the console is saying cohort1.sayName is not a function.


Solution

  • You have to set the methods onto the prototype. What you have done in your code is simply declare function local to the Cohort function scope, therefore they are NOT methods.

    Whenever you call new Cohort(...), an object is chained (new Cohort().__proto__ === Cohort.prototype) from the Cohort.prototype, which becomes this of your new Cohort object, where your properties will be saved onto. Setting Cohort.prototype.methods used the prototype chain logic to allow calling of these methods on each instance of the Cohort object

    var Cohort = function(program, campus, number, students) {
        this.program = program
        this.campus = campus
        this.number = number
        this.students = students
    }
    
    Cohort.prototype.sayName = function() {
      return `This cohort is called ${this.program}, ${this.campus}, ${this.number}.`
    }
    
    Cohort.prototype.takeAttendance = function() {
      return console.log(this.students)
    }
    
    var cohort1 = new Cohort("w", "pr", 27, ['devin', 'ben', 'bob'])
    var cohort2 = new Cohort('w', 'pr', 31, ["Brendan Eich", "Dan Abramov", "Wes Bos", "Kent Dodds"])
    
    console.log(cohort1.sayName())
    cohort1.takeAttendance()
    
    console.log(Object.getOwnPropertyNames(cohort1))
    console.log(Object.getOwnPropertyNames(cohort1.__proto__))

    In ES6, you can simply do

    class Cohort {
      constructor(program, campus, number, students) {
        this.program = program
        this.campus = campus
        this.number = number
        this.students = students
      }
    
      sayName() {
        return `This cohort is called ${this.program}, ${this.campus}, ${this.number}.`
      }
    
      takeAttendance() {
        return console.log(this.students)
      }
    }
    
    var cohort1 = new Cohort("w", "pr", 27, ['devin', 'ben', 'bob'])
    var cohort2 = new Cohort('w', 'pr', 31, ["Brendan Eich", "Dan Abramov", "Wes Bos", "Kent Dodds"])
    
    console.log(cohort1.sayName())
    cohort1.takeAttendance()
    
    console.log(Object.getOwnPropertyNames(cohort1))
    console.log(Object.getOwnPropertyNames(cohort1.__proto__))

    This class construct is actually just a syntactical sugar implementing same the logic as in ES5

    As an extra note, the below code also works, but usually not preferred. Notice the difference of where methods are stored (check the last 2 console.logs and compare with above ones)

    var Cohort = function(program, campus, number, students) {
        this.program = program
        this.campus = campus
        this.number = number
        this.students = students
        
        this.sayName = function() {
      return `This cohort is called ${this.program}, ${this.campus}, ${this.number}.`
        }
        
        this.takeAttendance = function() {
          return console.log(this.students)
        }
    }
    
    var cohort1 = new Cohort("w", "pr", 27, ['devin', 'ben', 'bob'])
    var cohort2 = new Cohort('w', 'pr', 31, ["Brendan Eich", "Dan Abramov", "Wes Bos", "Kent Dodds"])
    
    console.log(cohort1.sayName())
    cohort1.takeAttendance()
    
    console.log(Object.getOwnPropertyNames(cohort1))
    console.log(Object.getOwnPropertyNames(cohort1.__proto__))