Arrow functions and this

From the mozilla documentation on arrow functions:

function Person() {
  // The Person() constructor defines `this` as an instance of itself.
  this.age = 0;

  setInterval(function growUp() {
    // In non-strict mode, the growUp() function defines `this` 
    // as the global object (because it's where growUp() is executed.), 
    // which is different from the `this`
    // defined by the Person() constructor. 
    this.age++;
  }, 1000);
}

var p = new Person();

I think I understand that growUp() should be replaced by an arrow function in order to access the this on the person constructor because arrow functions do not have their own this. And that before arrow functions in order to make growUp increase age the solution would be to store the value of the Persons this inside a variable.

What I is not clear to me about the above example:

  1. What I want to understand is why arrow functions cannot have their own this?
  2. are there any similarities between arrow functions and iifes?
  3. Is it correct to say that
function growUp() {
    this.age++;
  } 

will effect right sided lookup?
4. Can someone please explain to me why growUp thinks that this refers to the global object?
5. So if your not using strict than what happens in the above example is growUp will pollute the global with an annonymous?? variable and apply a growUp method to it? Or it just tries to apply a method on a global object but is unsuccessful because it does not find any ‘age’

All help and explanations appreciated.

Ok so here’s a short tutorial.

var person1 = function(){
  console.log(this);
};
function person2(){
  console.log(this);
};
function Person(){
   console.log(this);

   anyInnerFunction();

   function anyInnerFunction(){
       console.log(this);
   }
}

person1(); // window object
person2(); // window object

var kerafyrm = new Person();
// kerafyrm object
// window object

ifee create new window objects

(function(){
  this.a = 1; // window.a = 1;
})();



(function(){
    console.log(this.a); //error
})();

look at setInterval as an inner function.

i think you meant to write this instead?

As well in your first iife example if it is creating a variable A and setting its value to 1 in the global scope it is a left sided lookup in your first iife example, whereas your second iife example would effect a right sided lookup is this correct? so why does your second iife throw a reference error ? I would think your second iife should go up the scope chain looking for an A value since its trying to perform some operation with it (console.log) and since it has been previously created and set in the global scope by your first iife why throw an error when trying to console.log it? this I did not understand. Please explain my mistake.

Correct. Window object displays 1st.

The 2nd iffe creates a new window object. So the property a doesn’t exists in the 2nd window object.

Because that’s how they were designed. They do not have this bound to them (on purpose). This means they inherit this from the nearest parent scope, as they appear in the code.

They are both functions.

No idea what this is, can you explain what you mean?

The function that setInterval repeatedly calls is executed in the global scope. this in the global scope is window (in the browser, there are other contexts with different names). So when you execute the function, you’re telling it to look for a property called age on that global object. There may or may not be a property called age present there: regardless, it isn’t the thing that you want to change.

The latter. "use strict" tries to stop you accidentally modifying that object. If this isn’t explicitly defined, it evaluates to undefined. In this case, when accidentally trying to assign to the global object, what you’re attempting in strict mode will be undefined.age++, which fails and throws an error.


this is a keyword available in functions (like arguments), and refers to the thing to the left of the dot (as.in.an.object.lookup): the calling object. But the value of this depends on how the function was called, not where it is defined in the code.

Say you’ve created a Person object called person (like var person = new Person()). It creates an object in the parent scope, which if it’s global, is window. And it has a property called age. If I ignore the setInterval:

window {
  person {
    age
  }
}

So person.age is 0. window.person.age is exactly the same.

new does something special, and this is what I mean by the value of this depending upon how the function was called. new creates a new object, and the value of this in the constructor function is set to that brand new object.

setInterval, though is a method of the window object:

The setInterval() method, offered on the Window and Worker interfaces, repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.

It executes a function in that global scope. So when growUp is executed, it’s in the scope of window. And it has it’s own this value within it. It’s almost like this: function growUp(callingObject) { callingObject.age++ }, except using the this keyword means it automatically gets passed the calling object.

So if we now include growUp on the diagram:

window {
  person {
    age
  }
  growUp()
}

growUp executes, the code inside it is evaluated, the code is this.age++. The calling object is window.

window {
  person {
    age
  }
  age++
}

this.age++ is window.age++, and it all falls over.

So

If you use an arrow function, arrow functions do not bind a this value. Instead, the this value in that function comes from the surrounding function - it just passes straight through. What that means in practice is that when you do new Person, this inside it gets set to that instance of Person, and this inside the setInterval will get evaluated to it too. Basically, in this context, it makes things a bit more sane: you can see that function is inside Person in the code, it seems obvious what growUp should do. But without the arrow function it does unexpected things (due to where this gets its value from when growUp executes). With the arrow function, the code in Person actually executes using the values defined on Person

sorry for wall of text (and for any small errors — it was typed on a phone and it proved a bit difficult to copy-edit, + explanation could’ve been simpler I think)

1 Like