4

I am using vue.js in this case but I guess it would apply in plain JS too. The problem is that when I am in a function that is in another function I am having to call variables by their full path like - Object.variable instead of this.variable. Is there a way to use this.timer, this.pages instead of TVComponent.pages etc.

const TVComponent = new Vue ({
el: '.tvContent',

data:
{
    current_page: 0,
    timer: 0,
    pages: [
      { page: '/', interval: 10 },
      { page: 'tv/calls', interval: 10 },
      { page: 'tv/general', interval: 10 }
    ]
},

methods:
{
  tvTimer()
  {
     setInterval(function() {
        TVComponent.timer++;

        if (TVComponent.timer == TVComponent.pages[TVComponent.current_page].interval) {
           console.log('it is time!!');
        }

        console.log(TVComponent.pages[TVComponent.current_page].page);
     }, 1000);
  },
})

4 Answers 4

2

Classic problem of this being not what you expect in a function

A. bind it

methods:
{
  tvTimer()
  {
     setInterval(function() {
        // ...
     }.bind(this), 1000);
  },
})

B. use a closure

methods:
{
  tvTimer()
  const _this  = this
  {
     setInterval(function() {
        _this.timer ...
     }, 1000);
  },
})

C. use an arrow function

methods:
{
  tvTimer()
  {
     setInterval(() => {
        this.timer ...
     }, 1000);
  },
})

This is one of those things one has to really understand about JS in order to not fall for it over and over in different places. I suggest this ebook:

https://github.com/getify/You-Dont-Know-JS/blob/master/up%20%26%20going/ch2.md#this-identifier

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I did not know about binding and arrow functions. Will need to read up on it!
1

The function you pass to setInterval receives its own context, however if you use an arrow function it will use the current context instead, and ignore the one given by setInterval.

setInterval(() => { ... }, 1000)

Comments

0

This is because setInterval() this object is not same as vue.js this, since they have different scopes.

Try to assign this object to new variable before entering the problematic function's scope.

let self = this;
tvTimer()
  {
     setInterval(function() {
        self.timer++;

        if (self.timer == self.pages[self.current_page].interval) {
           console.log('it is time!!');
        }

        console.log(self.pages[self.current_page].page);
     }, 1000);
  },

See: https://developer.mozilla.org/en-US/docs/Glossary/Scope

Comments

-1

I think you have to bind it in this context. We do it this way in React classess.

2 Comments

how do you bind it?
You can use data.timer that is a better way

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.