0

I am using Typescript for an Angular 2 project. I notice that when we use the keyword this inside a labmda expression vs a function, this refers to different things.

For example, let's say I have an Angular component like the following.

export class MyComponet {
 isActive = true;
 names = [ "john", "jeff", "jared" ];

 doSomethingWithLambda() {
  names.forEach( (value, index) => {
   if(this.isActive) { //this.isActive refers to MyComponent.isActive
    //do something...
   }
  });
 }

 doSomethingWithFunction() {
  names.forEach( function(value, index) {
   if(this.isActive) { //this.isActive is undefined, since this refers to the function
    //do something
   }
  });
 }

 doSomethingWithFunction2() {
  let isActive = this.isActive;
  names.forEach( function(value, index) {
   if(isActive) { //if we change isActive will this also change MyComponent.isActive?
    //do something
   }
  });
 }
}

What is really happening here (behind the scene, so to speak)? What's the magic behind this inside a lambda that makes it able to "correctly" refer to the outer class' fields? I understand this inside a function will refer to the function itself.

Also, I have a doSomethingWithFunction2 method that will reference MyComponent.isActive into a local variable. If I change that local variable, that should be like changing the one it references, right? (regardless of it being a "primitive" like integer/number or an "object" like JSON { })

Jane Wayne
  • 8,205
  • 17
  • 75
  • 120

2 Answers2

2

The fat-arrow function syntax is shorthand for:

function () { }.bind(this);

bind is a Javascript ES5 method equivalent to this:

Function.prototype.bind = function bind(context) {
  var func = this;
  return function () {
    return func.apply(context, arguments);
  };
}

In regards to

Also, I have a doSomethingWithFunction2 method that will reference MyComponent.isActive into a local variable. If I change that local variable, that should be like changing the one it references, right? (regardless of it being a "primitive" like integer/number or an "object" like JSON { })

In Javascript, variables are like pointers and except for some limited cases (primitives and copy-on-write objects) will change the referenced value when mutated. Reassigning will not change the original value, e.g. isActive = false; but this.isActive = false would in fact re-assign the variable isActive on this which is now hopefully correctly assigned.

CaptEmulation
  • 4,416
  • 2
  • 17
  • 14
0

This has to do with how lambda function are implement in TS. this in arrow function is lexically inferred so it more in line with below code

function Person() { var self = this; // Some choose that instead of self. // Choose one and be consistent. self.age = 0;

setInterval(function growUp() { // The callback refers to the self variable of which // the value is the expected object. self.age++; }, 1000); } So inside the lambda function it is not actually this but a context closer self. This may not be actual implementation but much closer to give you understanding of what is happening.

Now when you are outside the my impotent this refers to global var which would be window

The lambda function is similar to javascripts bind function.

Protip see your transpiled JS how your lambda function is transforming.

Arpit Agarwal
  • 3,993
  • 24
  • 30