Reputation: 674
I'm running into the undefinded
error when trying to access the this.numberObject
from another function init
.
I'm pretty sure it's because my this
keyword is referencing the window object.
My problem is that I can't figure out an elegant way to structure my code.
Current Code:
class IncrementNumbers {
constructor() {
this.numberObject = document.querySelector(".incrementNum");
if (this.numberObject != null) {
console.log(this.numberObject.innerHTML);
this.num = this.numberObject.innerHTML;
this.events();
}
}
events() {
console.log("events function ran");
this.init();
}
init() {
let target = 345;
let current = 0;
function addOneToElement() {
if (current === target) {
clearInterval(addOne);
}
current++;
this.numberObject.innerHTML = current; <---- ERROR HERE
}
let addOne = setInterval(addOneToElement, 10);
}
}
export default IncrementNumbers;
Error:
IncrementNumbers.js:44 Uncaught TypeError: Cannot set property 'innerHTML' of undefined
I can fix the error by adding in
this.numberObject = document.querySelector(".incrementNum");
to the following function
init() {
let target = 345;
let current = 0;
function addOneToElement() {
this.numberObject = document.querySelector(".incrementNum"); <--- ADDED HERE
if (current === target) {
clearInterval(addOne);
}
current++;
this.numberObject.innerHTML = current;
}
let addOne = setInterval(addOneToElement, 10);
}
However this feels a bit redundant because I'm already referencing the element Object in my constructor. I'd like the function, init
to run once the page has loaded.
Is there a better way?
Thank you
Upvotes: 0
Views: 51
Reputation: 2408
The problem is the inner function addOneToElement
that creates its own this
context within init.
A simple fix would be to use arrow functions which don't have a this context:
class IncrementNumbers {
init() {
let target = 345;
let current = 0;
// Use an arrow function here.
const addOneToElement = () => {
if (current === target) {
clearInterval(addOne);
}
current++;
this.numberObject.innerHTML = current; <---- ERROR HERE
}
let addOne = setInterval(addOneToElement, 10);
}
}
Another option would be to bind the this context to addOneToElement:
let addOne = setInterval(addOneToElement.bind(this), 10);
Upvotes: 1
Reputation: 121
Your problem seems to come from a misspropagation of the this
object.
In your function init
you set a new function named addOneToElement
that is called inside of a setInterval
, this setInterval
instance
does not have access to the this
element of your class
.
To fix the problem you could try to do something like
class IncrementNumbers {
constructor() {
this.numberObject = document.querySelector(".incrementNum");
if (this.numberObject != null) {
console.log(this.numberObject.innerHTML);
this.num = this.numberObject.innerHTML;
this.events();
}
}
events() {
console.log("events function ran");
this.init();
}
init() {
let target = 345;
let current = 0;
function addOneToElement() {
if (current === target) {
clearInterval(addOne);
}
current++;
this.numberObject.innerHTML = current; // <---- ERROR HERE
}
let addOne = setInterval(addOneToElement.bind(this), 10);
}
}
export default IncrementNumbers;
let addOne = setInterval(addOneToElement.bind(this), 10);
Where you bind the this
instance
of your class
to the function addOneToElement
.
Upvotes: 1