damitj07
damitj07

Reputation: 2909

Context and variable scope in ES6 loops and forEach

In ES5, if I have to refer to the this context of parent function in child function I have to store it in a variable and access it inside child function using that variable.

Something like this ...

//  variant 1
var self = this;
this.nums.forEach(function (v) {
if (v % 5 === 0)
   self.fives.push(v);
});

ECMAScript has arrow functions so I can avoid this:

// variant 2
this.nums.forEach((v) => {
 if (v % 5 === 0)
   this.fives.push(v)
})

The question that I have is: If I was to declare a variable temp inside my forEach function above will this pollute my global scope? If so will this have performance issues and variable conflicts?

Something similar happens in for loop ....

//variant 3
for(var i =0 ;i.......){
   var temp = "tempvariable";
   //some code here
 }

 console.log(temp);
 //output : tempvariable

What is the difference between variant2 and variant3 code snippets?

Upvotes: 4

Views: 4377

Answers (1)

adeneo
adeneo

Reputation: 318302

Regular functions use execution context to set the value of this, meaning that in in most cases, the value of this is determined by how a function is called, i.e. the value of this is set according to the environment in which the function is executed.

Arrow functions do not have their own this value, instead they use lexical scoping, meaning the value of this inside an arrow function is always inherited from the enclosing scope, i.e. it is set to the this value of the enclosing execution context.

This is explained in the documentation as well

Until arrow functions, every new function defined its own this value (a new object in case of a constructor, undefined in strict mode function calls, the context object if the function is called as an "object method", etc.). This proved to be annoying with an object-oriented style of programming.
....
Arrow functions capture the this value of the enclosing context

The third example posted is just a regular for loop, and has very little in common with functions, and can't really be compared to the two first code examples.
for loops work the same in ES2015 as they always have, there generally is no special scope in for loops for variables, as variables (defined with var) are function scoped.

However, ES2015 does introduce variables that can are block scoped as wel, and as a for loop is in fact a block (for (what) {block}), those variables can be used, and they are defined with either the let keyword, or the const keyword for a constant (that can not be changed) .

For those that prefer code

var o = {
    nums  : [1,2,3,4],
    fn    : function() {
        var self = this;
        this.nums.forEach(function(v) {
            // "this" in this context would be the window,
            // but "self" would be the object "o", hence the common use of this hack
        });

        this.nums.forEach((v) => {
            // "this" in this context, would be the object "o"
            // that happens because the "this-value" in the fn() function,
            // ... is the parent object
            // and the arrow function inherits that this-value
        });

        for (var i=0; i<this.nums.length; i++) {
            // "this" in this context is what it has always been,
            // a for-loop has the same this-value as the surrounding scope
        }
    }
}

o.fn(); // called from global context "window"

Upvotes: 6

Related Questions