1

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.

6
  • 2
    You need to add that method to the prototype of Cohort, if you want to use it in the manner specified. See Object.prototype for more. Commented Mar 12, 2018 at 17:30
  • 6
    Declaring the function inside the constructor does not make it a property value of the constructed object. It's just a local function. You can make it a property by adding this.sayName = sayName;. Commented Mar 12, 2018 at 17:31
  • 1
    @Pointy but won't that only ever print out the local values of the variables mentioned? If something were to change this.program, the output of sayName would not reflect it, right? In other words, I think what you posted would work, but I'm not sure it reflects the OP's intention (though who knows). Commented Mar 12, 2018 at 17:35
  • 1
    @rmlan no; the "sayName" function refers to the constructor arguments, not the object properties. Those will never change. Commented Mar 12, 2018 at 17:36
  • @Pointy That's what I was saying. I can't know for sure, but I have a feeling that is in contention with what OP actually wants. Commented Mar 12, 2018 at 17:37

3 Answers 3

3

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__))

Sign up to request clarification or add additional context in comments.

1 Comment

thanks so much, I tried doing it as a class earlier but it wasn't working, this makes a lot more sense.
1

To use a function inside a function, you have to assign it using the same way you assigned the properties.

You can do that by adding this:

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(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())

...or using prototype (preferred method for most devs):

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())

Comments

0

Constructor invocation is performed when new keyword is followed by a function name, and a set of opening and closing parentheses.

const person = function(name, age) {
    this.name = name;
    this.age = age;

    this.showDetails = function() {
        console.log(this.name + " is " + this.age + " years old");
    }
}

const sean = new person('Sean', 35);
sean.showDetails(); // Sean is 35 years old

Constructing objects in JavaScript is just one method among several for object creation.

Read more: https://medium.com/p/1112c925e78f

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.