31

Could someone please give me a brief introduction to lexical this?

"An arrow function expression (also known as fat arrow function) has a shorter syntax compared to function expressions and lexically binds the this value (does not bind its own this, arguments, super, or new.target). Arrow functions are always anonymous."

Does it mean that when I call a function member using the 'this' ref from a 'Fat Arrow' Function the 'this' always refers to the enclosing 'this'?

Gorilla
  • 553
  • 1
  • 6
  • 11
  • 8
    Yes, `this` in an arrow function has the same value as the context in which the arrow function was created. – Pointy Jan 09 '16 at 17:35
  • lets say u are having click listener in that listener u are performing some ajax operation like setTimeout.after the time has completed the code inside the callback will get executed.inside that callback you may have accessed this for changing color of the clicked button.but the control will be out of that context due to ajax operation.so you cannot access this.so es6 introduced arrow function to fix tat problem – sundar Jan 09 '16 at 17:39
  • 2
    [This post from @getify](http://blog.getify.com/arrow-this/) is an absolute must-read on the subject of the so-called *lexical `this`* – CodingIntrigue Jan 09 '16 at 18:36
  • 5
    Lexical `this` simply means that `this` is looked up in lexical scope. I guess that was actually always the case. Maybe it is easier to understand if we say that an arrow function doesn't have an own `this` value. – Felix Kling Jan 09 '16 at 20:06
  • http://stackoverflow.com/a/32539428/1048572 – Bergi Sep 25 '16 at 14:07
  • What don't you understand from all the blog entries, SO Q&A, and tutorials out there? Is your confusion with the word "lexical"? By the way, these are no longer called "fat arrows" or "fat arrow functions". –  Sep 25 '16 at 17:13

6 Answers6

44

You seem to have the correct understanding of what happens with this in an arrow function. I will offer an explanation that I think adds to the conversation and hopefully solidifies your understanding.

As you probably know, when you define a function and use a variable inside of it, it checks if the variable has been defined in its scope. If it is, it uses it! If not, it checks the enclosing scope for that variable definition. It keeps checking enclosing scopes until it finds the variable or reaches global scope. Now, function definitions that are not arrow functions define this for you, implicitly. Thus, they will never check an enclosing scope when you try to use this in their scope (because they find it in their own scope!). Arrow functions do NOT define their own this, so they go to the enclosing scope and look for it just as they would with any variable you try to use in their scope.

jakeehoffmann
  • 1,364
  • 14
  • 22
  • This is just wrong. Variables are found along the entire scope chain. `this` is "found", in the case of arrow function, exactly in the **immediately** enclosing scope. –  Jul 07 '17 at 11:07
  • 6
    I'm not sure we disagree. Perhaps I was unclear. Regarding your last sentence: what about nested arrow functions? – jakeehoffmann Jul 08 '17 at 01:27
  • Thanks! It clicked for me after reading this answer. It made me realize that within the same scope variables and `this` are defined independently of each other. – Andru Mar 21 '18 at 12:48
  • It's hardly an enclosing scope if you can escape from the scope though... WHy aren't JS folks talking about threads? It would be more consistent. – chrips Feb 26 '19 at 12:36
14

As a way to describe the behavior of this in arrow functions, the term "lexical this" is somewhere between confusing and wrong.

The behavior is quite simply is that this in an arrow function refers to the this in the surrounding function--or perhaps it would be simpler and more accurate to just say that the arrow function does not define (or "bind") its own this.

The unfortunately terminology of "lexical this" may have been perpetuated by a poor choice of wording in the MDN article on arrow functions (which until recently also encouraged people to use the obsolete term "fat arrow function"). This has now been cleaned up. Note also that the spec never uses the term "lexical" in relation to this in arrow functions. I'd be curious to know who came up with this expression.

  • 2
    Actually the current ECMA 2022 version does call the two possible values of "this" used to build a function evaluation context `lexical-this` and `non-lexical-this`, the meaning of which relates to the function "internal slot" `[[ThisMode]]`, whose definition states: "`lexical` means that `this` refers to the `this` value of a lexically enclosing function". In version 6 this was simply stated in paragraph 14.2.16 (in short, about the evaluation of an arrow function :) ) as "Let scope be the LexicalEnvironment of the running execution context". Bloody confusing indeed. – kuroi neko Jul 27 '21 at 18:06
8

Lets say you have a click listener. In that listener you are performing some AJAX operation like setTimeout. After the set time has been reached, the code inside the callback will be executed. Inside that callback you may have accessed this to change the color of the clicked button. But the control will be out of context due to AJAX operation. ES2015 introduced the arrow function to fix that problem. The arrow function captures the this value of the enclosing context.

The example use-case is:

$('.btn').click(function () {
    setTimeout(function () {
        $(this).text('new'); 
        // This will cause an error since function() defines this as the global object.
    } ,100); 
}); 

To avoid this case:

$('.btn').click(function () { // <- Enclosing context
    setTimeout( () => {
        $(this).text('new')  } 
        // This works, because this will be set to a value captured from the enclosing context.
      ,100);
});
Community
  • 1
  • 1
sundar
  • 398
  • 2
  • 12
2

I wrote an article about this, the gist of which is: do not think about what "lexical this" means. Do not worry about what "this" means within an arrow function. You already know (or at least, if you don't, it's the fault of your own confusion about some outer functional scope, and not the fault of the arrow function).

You may have been conditioned over the years to get anxious about what "this" would end up meaning when you needed to use it within some nested or higher-order function. But with arrow functions, you just can STOP worrying about it. You almost certainly already know what "this" refers to in the context that you're currently in: BUT... within the arrow function, it hasn't changed. So you can think of arrow functions as the simple case, and function(){} as the more complex one.

Do you write some function and start an if(){} block and worry about what "this" could have changed to inside it? No? Same with arrow functions. That's what "lexical this" means. It means "Hakuna matata."

Dtipson
  • 1,564
  • 16
  • 21
  • 1
    It strikes me as a bit odd to say that the behavior of `this` for the last twenty years, and which lies at the heart of all JS code, is "complex". What is complex about it? If that is complex, all that arrow functions do is pass off that complexity to the enclosing function scope by not defining their own `this`. –  Sep 25 '16 at 17:15
  • You explain it like if arrow functions always behaved as desired, and normal functions never. But the `this` behavior for normal functions is also useful, e.g. when defining methods in a prototype. – Oriol Sep 25 '16 at 17:54
  • Arrow functions do not alter the current meaning of "this." Therefore, no extra special, confusingly explained new mental model like "they bind the meaning of this at write-time" is needed to understand what their "this" refers to. What it refers to hasn't changed. That's it. And yes, regular functions are objectively more complex. They have several more dynamic properties to worry about. That they've been around for 20 years has no bearing on that question. Yes they're still useful. But they're no longer the only tool for the job. I'm just saying: use a simpler one when you can. – Dtipson Sep 26 '16 at 21:01
  • The point is simply that instead of gearing up your brain to think of arrow functions as having some special new behavior towards the meaning of this which you now have to sit down & learn, it's far easier to just think of them as having NO behavior. Yes, you might still have to think about the meaning of "this" if you use it in an arrow function. But that's not the arrow function's fault, or a new complexity it's added to the mix. – Dtipson Sep 26 '16 at 21:03
1

Does it mean that when I call a function member using the 'this' ref from a 'Fat Arrow' Function the 'this' always refers to the enclosing 'this'?

The answer to your query is Yes. As you have already stated fat arrow functions don't have a this reference so they use the reference of the enclosing context, which in turn, gives us a chance to control how the call to this inside a fat arrow function would respond.

For e.g.:

Having fat arrow function inside an object which makes use of this would look for outer context. In this case, the context is window:

var foo = {
  bar: () => this.baz    // 'this' is window      
}

However, if you use the ES6 syntax which is public class field syntax:

class MyClass {
  handleEvent = () => {
    this.letsCode();    // 'this' is instance of MyClass
  }
}

There are many other instances (like using in render function of React on an HTML element to set click listeners) which are out of the scope of this question where fat arrow functions are used and this is appropriately bound to the context in which it is used thus giving us the facility to control its nature. Hope it helps!

patrick.1729
  • 4,222
  • 2
  • 20
  • 29
-1

Using this in es6 fat arrow function, makes this to have lexical scope in the sense that what this refers to in that particular scope is assigned to it, unlike the normal es5 function declaration which keeps checking for what this is referenced to starting from the innermost scope to the global scope till it finds it.

function foo() {
setTimeout(() => {
    // `this` here is lexically adopted from `foo()`
    console.log( this.a );
},100);
}
var obj = {
  a:2
};
foo.call(obj); //2

Meanwhile, pre es6, there was a way to implement lexical scoping in javascript, by assigning a this keyword to a variable, which to an extent makes this local to the scope

function foo() {
var self = this; // lexical capture of `this`
setTimeout( function(){
    console.log( self.a );
}, 100 );
}
var obj = {
  a: 2;
};
foo.call(obj); //2
Jude
  • 1
  • 6
  • The `this` identifier does follow the usual scope chain. What makes it special is that it is redefined in the local scope of usual functions when building their execution context, depending of the type of the function (object method or unbound function) and the use of "strict" mode. For an arrow function, `this` is not redefined, so it is simply resolved in the upper scope. See [the note](https://262.ecma-international.org/6.0/#sec-arrow-function-definitions-runtime-semantics-evaluation) in the current specs (version 6 says the same, in a slightly more cryptic way). – kuroi neko Jul 27 '21 at 19:14