Difference between two similar functions, why is one working and the other not

155 Views Asked by At

I have two functions, one working, the other not.

They are equal, except that the one is looping through a variable, in which the global object of the scope is saved (hope this makes sense), and the other tries to loop through the text directly, but fails, because it throws the error:

Uncaught TypeError: Cannot read property '0' of undefined

Here is the fiddle:

http://jsfiddle.net/4p1p4wjy/2/

In my understanding, the 2nd version of the function is not working, because it somehow can't access the this.splittedText, from within the callback of the function.

First Working Function:

        loopThroughSplittedText: function() {
            // delete this
            var locationInString = 0;
            var splittedText = this.splittedText;

            function delayedOutput() {
                document.getElementById('output').innerHTML = splittedText[locationInString];

                locationInString++;

                if(locationInString < splittedText.length) {
                    setTimeout(delayedOutput, 200);
                }
            }

            delayedOutput();
        },

Second Not Working Function:

        loopThroughSplittedTextNotWorking: function() {
            // delete this
            var locationInString = 0;

            function delayedOutput() {
                document.getElementById('output').innerHTML = this.splittedText[locationInString];

                locationInString++;

                if(locationInString < this.splittedText.length) {
                    setTimeout(delayedOutput, 200);
                }
            }

            delayedOutput();
        }

How do I make the 2nd function work, without saving the object inside a local variable first? I'd like to use the two-way databinding as best as possible.

2

There are 2 best solutions below

0
On BEST ANSWER

Simple answer, you don't. Because your function is called through timeout, it's not in the same context anymore and 'this' will not refer to the same object anymore.

You can do this:

        loopThroughSplittedTextNotWorking: function() {
        // delete this
        var locationInString = 0;

        var that = this;

        function delayedOutput() {
            document.getElementById('output').innerHTML = that.splittedText[locationInString];

            locationInString++;

            if(locationInString < that.splittedText.length) {
                setTimeout(delayedOutput, 200);
            }
        }

        delayedOutput();
    }

By saving the "this" variable into a local variable, you can access it in your "delayedOutput" function.

I realize it's basically just like your working example, just phrased a little different, but that's usually how I do it.

0
On

How do I make the 2nd function work, without saving the object inside a local variable first?

You can't. this is a variable that is always local to the function it is used in, and its value depends on how the function is called. If you want to use its value in a different function, then you need to copy it into another variable.

The bind method provides a shorthand for doing that.

setTimeout(delayedOutput.bind(this), 200);