Home > other >  call() method is not working with functions
call() method is not working with functions

Time:12-24

function Student(name, age, prof) {
  this.name = name;
  this.age = age;
  this.prof = prof;
  this.msg1 = function() {
    console.log(`my name is ${this.name} my age is ${this.age} and i love ${this.prof}`)
  }
  this.msg2 = function() {
    console.log(`my name is ${this.name}my age is ${this.age} and i love ${this.prof}`)
  }
}
//new Student("jack",17,"hacking").msg1() //this works fine
//new Student("rose",21,"hacking").msg2() // this too works fine
Student.call({}, "jack", 17, "hacking")
Student.msg1()

CodePudding user response:

The first argument of call is the replacement value for this.

So you are creating a new, empty object and passing it as the this value to Student. The Student function then modifies that object. Then the object, with the values just added to it, is thrown away because you do nothing to keep any references to it.

You then try to call msg1() on the Student function object, but it doesn't exist there because you never assign a value to the msg1 property of that object.


Now you could pass Student itself as the this value.

Student.call(Student, "jack", 17, "hacking")

and then the next line of your code would work.

I don't recommend that you do though.


Or you could create an object, keep a reference to it, and then use that.

const jack = {};
Student.call(jack, "jack", 17, "hacking")
jack.msg1();

Which is less horrible, but still not great.


call is useful when you need to borrow a method from an object, such as when you have an array-like object and you want to use a real array method on it.

Student is designed to work as a constructor function. You should use it as one.

const jack = new Student("jack",17,"hacking");
jack.msg1();

If you wanted to redesign it to modify an existing object, then it would be better to write it as a regular function which expected the object you wanted to modify as an argument.

CodePudding user response:

I understand that I am repeating what Quentin said, but, I have a straight forward answer.

function Student(name, age, prof) {
  this.name = name;
  this.age = age;
  this.prof = prof;
  this.msg1 = function() {
    console.log(`my name is ${this.name} my age is ${this.age} and i love ${this.prof}`)
  }
  this.msg2 = function() {
    console.log(`my name is ${this.name}my age is ${this.age} and i love ${this.prof}`)
  }
}

Student.call({}, "jack", 17, "hacking");

When you use .call function, the first parameter to it becomes this inside the function. So, when you say .call({}, ...), the {} becomes the this inside the function. The same will be populated with name, age, prof, msg1, msg2 properties. So, it worked as it is expected to.

The problem is with your understanding. You thought that, doing Student.call({}, ...) will add the name, age, prof, msg1, msg2 properties in Student. As I mentioned above, those properties are populated in the {} that you passed as the first parameter.

So, if you want to access the properties created inside the Student constructor, then create a reference to the first parameter & pass that to the .call function. Then, you can access those properties, through the reference, as follows:

const student = {};
Student.call(student, "jack", 17, "hacking");

student.name; // jack
student.msg1() // my name is jack my age is 17 and i love hacking

But, as Quentin advised, do not use this pattern to create object instances. Use the constructor instead.

  • Related