Reputation:
I feel my whole understanding of this
has been thrown up in the air.
I have a Quiz
object which holds the necessary variables and methods required to play the quiz.
I am trying to reference a method of Quiz from another method in Quiz (getQuestion
in skipQuestion()
) however, I am seeing a message in the console saying that this.getQuestion
is not defined. I was under the impression that this
in this case refers to the object it is in, hence the function in question should be referred to as this.getQuestion()
.
The error message I am getting is script.js:18 Uncaught TypeError: this.getQuestion is not a function
Can anyone explain what is going wrong here?
In my init
function it seems that this
refers to the Quiz
object, but in skip question
it seems to change. Is this down to query having a different definition of this
? where do you draw the line, and when is the context of this
changed?
(function(window){
$(document).ready(function(){
var Quiz = {
score : 0,
question: '',
answer: '',
init: function() {
this.getQuestion();
this.checkAnswer();
this.skipQuestion();
},
skipQuestion: function() {
$('#skip').click(function(){
this.getQuestion();
})
},
getQuestion: function() {
$.get('http://jservice.io/api/random', function(data){
$('#question').html(data[0].question);
this.answer = data[0].answer.toLowerCase();
});
},
checkAnswer: function() {
if($('#answer').val() === this.answer) {
this.score += 1;
}
}
}
Quiz.init();
});
})(window);
Upvotes: 0
Views: 134
Reputation: 17340
Because you are nesting inside another function, the this
context changes to that function, so the methods you look for are no longer available. You can try to solve it by either storing the this
inside a variable that will be within the scope of the function you are defining, or by using Double Arrow Functions, which have no associated this
context themselves (and therefor also don't support bind
or call
). Here are your options:
Declare a variable:
skipQuestion: function() {
var that = this;
$('#skip').click(function(){
that.getQuestion();
})
}
or a Double Arrow Function:
skipQuestion: function() {
var that = this;
$('#skip').click(() => that.getQuestion())
}
Your init function is considered a method of your Quiz object, while the anonymous function passed to the click event is not a method of your Quiz, it is a method of an anonymous object created in the background, and shares no methods or variables with your Quiz. This is important to consider!
Upvotes: 1
Reputation: 281686
The thing is you are using this
inside the click event and it refers to the event rather than you context. To work around you need to assign this to another variable and then use that;
skipQuestion: function() {
var self = this;
$('#skip').click(function(){
self.getQuestion();
})
},
$.get
and .click
event create their own context and thus this
refers to their context instead of the context of quiz.
JS
(function(window){
$(document).ready(function(){
var Quiz = {
score : 0,
question: '',
answer: '',
init: function() {
this.getQuestion();
this.checkAnswer();
this.skipQuestion();
},
skipQuestion: function() {
var self = this;
$('#skip').click(function(){
that.getQuestion();
})
},
getQuestion: function() {
var self = this;
$.get('http://jservice.io/api/random', function(data){
$('#question').html(data[0].question);
self.answer = data[0].answer.toLowerCase();
});
},
checkAnswer: function() {
if($('#answer').val() === this.answer) {
this.score += 1;
}
}
}
Quiz.init();
});
})(window);
Upvotes: 0