Jordan Davis Jordan Davis - 23 days ago 8
Javascript Question

using the 'this' variable within object constructor

I'm a bit confused on the result I'm getting when calling the 'this' variable inside in object constructor.

function Slider(tag){
this.tag = document.querySelector(tag),
this.start = function(){
return this.interval;
},
this.interval = setInterval(function(){
console.log(this.tag); //undefined
console.log(this); //window object
}, 2000)
}
var route ={
init:function(){
mySlide = new Slider('slider');
mySlide.start();
}
}
document.addEventListener('DOMContentLoaded', route.init);


I'm logging tag
console.log(this.tag)
however it's returning
undefined
and when logging the
this
variable inside
console.log(this)
it refers to the window object.

Here is a Demo

Question: Why isn't
console.log(this.tag)
returning the selected element?

Answer

This is because when you pass a callback function to setInterval, it's called in the global scope. That's why this is window.

You can use Function.bind() to set the context of the function to your this object and make it work as you want.

this.interval = setInterval(function(){
    console.log(this.tag);
}.bind(this), 2000);

Also, I just want to point out that mySlide.start(); does nothing. When you call new Slider('slider'), that's when your interval is set. Your mySlide.start(); just returns the intervalID (which is only used for clearInterval()). Actually since you are not even using the return value of mySlide.start();, calling it is useless.

UPDATE: Another solution is to use var self = this; in your constructor function and then use self inside setInterval():

function Slider(tag){
    var self = this;

    this.tag = document.querySelector(tag),
    this.interval = setInterval(function(){
        console.log(self.tag);
    }, 2000);
}

UPDATE: If you are on a browser that supports "arrow functions", then you can do this:

this.interval = setInterval(() => {
    console.log(this.tag);
}, 2000);
Comments