-2
var studentMarks = {
    mathScore : 0,
    englishScore : 0,
    totalScore : null,
    computeMarks : function (mathScore, englishScore) {
        this.mathScore = mathScore;
        this.englishScore = englishScore;
        this.totalScore = this.mathScore + this.englishScore;
        console.log(this.totalScore);
    }
}

function setStudentScore(score1,score2,callback){
    callback(score1,score2);
}

setStudentScore(40,50,studentMarks.computeMarks);
print(studentMarks.totalScore);  //prints 'undefined'

The print statement should print 90 instead it prints undefined. What changes should I do to the computeMarks method ?

Mohammad
  • 21,175
  • 15
  • 55
  • 84
  • 3
    Try `studentMarks.computeMarks.bind(studentMarks)` as callback – vp_arth Jun 07 '16 at 18:48
  • See http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback for some help on this topic. – Crescent Fresh Jun 07 '16 at 18:50
  • still didn't work @vp_arth. Any other idea ? – Manoj Verma Jun 07 '16 at 18:52
  • no help whatsoever @CrescentFresh . I am still confused in 'this'. – Manoj Verma Jun 07 '16 at 18:54
  • @ManojVerma, what exactly `didn't work`? add `console.log(studentMarks)` to callback. – vp_arth Jun 07 '16 at 18:54
  • @Redu : Yeah ! It was an interview question.Hence,had to deal with it. – Manoj Verma Jun 07 '16 at 19:02
  • As others have mentioned, where you have your callback defined originally, "this" points to window rather than studentMarks. – Pytth Jun 07 '16 at 19:03
  • @Pytth In the callback `this` refers to the `studentMarks` object. – Redu Jun 07 '16 at 19:14
  • @Redu, only when called as `studentMarks.computeMarks`. When it passed by value, it will called as simple function without any context(with global context in not strict mode). – vp_arth Jun 07 '16 at 19:20
  • 1
    @vp_arth You are right... By callback I had meant `studentMarks.computeMarks()` alone... However when it gets passed as a callback directly it's definition get's assigned to an argument variable of the function which invokes it (`setStudentScore()` in this particular case) hence looses the scope. Instead shall be passed wrapped in an anonymous to work as expected. Shown in my answer. – Redu Jun 07 '16 at 19:44
  • 1
    @vp_arth's comment [works fine](https://jsfiddle.net/jcnppetg/), you're messing something else up. You're not using IE 8 or something, are you? Also, the linked answer I posted explains everything, you need to make some modicum of effort here. – Crescent Fresh Jun 07 '16 at 20:54

5 Answers5

2
setStudentScore(40,50,studentMarks.computeMarks);

You pass just computeMarks value as callback here. It is a function, not original object method. There is not information about to what object this function related.

When it will called, this will point to global object.

Try to bind context directly:

setStudentScore(40,50,studentMarks.computeMarks.bind(studentMarks));
vp_arth
  • 14,461
  • 4
  • 37
  • 66
2

try

setStudentScore(40,50,studentMarks.computeMarks.bind(studentMarks));

In JS, the thing called this, is the object that "owns" the JavaScript code. In your case, looks like it was the function calling it. You can use bind to tell it what does this refer to in your context. Read this if you want

Scimonster
  • 32,893
  • 9
  • 77
  • 89
fkilaiwi
  • 21
  • 2
0

This should work for you

var studentMarks = {
    mathScore : 0,
    englishScore : 0,
    totalScore : null,
    computeMarks : function (mathScore, englishScore) {
        this.mathScore = mathScore;
        this.englishScore = englishScore;
        this.totalScore = this.mathScore + this.englishScore;
    }.bind(studentMarks)
}

function setStudentScore(score1,score2,callback){
    callback(score1,score2);
}

setStudentScore(40,50,studentMarks.computeMarks);

Working in console

dazlious
  • 546
  • 6
  • 23
0

Try this:

 var studentMarks = function() {
 var self = this;
 this.mathScore = 0;
 this. englishScore = 0;
 this.totalScore = null;
 this.computeMarks = function (mathScore, englishScore) {
  self.mathScore = mathScore;
  self.englishScore = englishScore;
  self.totalScore = this.mathScore + this.englishScore;
  console.log(self.totalScore);
 }
};

function setStudentScore(score1,score2,callback){
callback(score1,score2);
}

var obj = new studentMarks();

setStudentScore(40,50,obj.computeMarks);
console.log(obj.totalScore);  //prints 90
Nika
  • 1,864
  • 3
  • 23
  • 44
  • It works but the constraint is I can't change the print to console. The only changes I can make are 1) In this.computeMarks function & 2) In the two lines where I'm calling the callback. – Manoj Verma Jun 07 '16 at 19:10
  • `can't change the print to console` - Are you kidding? Where is `print` implementation, if not? – vp_arth Jun 07 '16 at 19:24
0

You may do it like this

var studentMarks = {
    mathScore : 0,
    englishScore : 0,
    totalScore : null,
    computeMarks : function (mathScore, englishScore) {
        this.mathScore = mathScore;
        this.englishScore = englishScore;
        this.totalScore = this.mathScore + this.englishScore;
        return this.totalScore;
    }
};

function setStudentScore(score1,score2,callback){
    callback(score1,score2);
}

setStudentScore(40,50,function(a,b){studentMarks.computeMarks(a,b)});
console.log(studentMarks.totalScore);
Redu
  • 25,060
  • 6
  • 56
  • 76