In the traverse
npm package there's this example
var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
traverse(obj).forEach(function (x) {
if (x < 0) this.update(x + 128);
});
Inside the callback function you can call this.update
. I know in these kinds of cases you should use the regular (not ES6 arrow) style of function definitions like shown above.
But out of curiosity, how would you make that code work with ES6 arrow function syntax? If I try as follows I get TypeError: Cannot read property 'update' of undefined
because of course this
is not the same as above.
traverse(obj).forEach((x) => {
if (x < 0) this.update(x + 128);
});
I tried to change this
by using bind
but wasn't successful. How do you change this
in ES6 arrow functions?
You can't, that's the whole point of using arrow functions (besides concise syntax). If you need to control
this
, don't use an arrow function.Arrow functions in ES6 have lexical this. This means you can always tell their
this
-value by asking the question "What was the value ofthis
when the function was defined?" They are immune to thethis
-altering effects of call, apply, bind, and method invocation.Let's take a look at the intended effect by compiling ES6 to ES5 with Babel.
ES6:
Compiled to ES5:
Check out what happened inside
foo.bar
. There was an inserted line:The arrow function's body was changed so that it returned
_this
from its lexical outer scope. Therefore, binding the value ofthis
is not supposed to have any effect. By "freezing" the value of "this" just before the function definition, we have prevented the ability to change the function's behavior through binding, using call/apply, or calling the function as a method.Notice how
baz
's this value was simply replaced withundefined
. That's because if we ask the question "What was the value ofthis
when the function was defined?", we obviously must answer eitherundefined
or some global object context, like Node'sglobal
or the browser'swindow
. By asking this question, you can easily deduce the value ofthis
inside arrow functions, and that is a big part of their inherent value.The output is therefore:
The first and third outputs correspond to the arrow function defined within
bar()
. Notice how they automatically have athis
-value that points to the object referred to byfoo
because they were created with thefoo.bar()
call. Useful right? Only the behavior of the non-arrow function could be changed by binding. Before binding, it'sthis
-value wasundefined
, a common cause of many JS bugs and redundant bindings when passing around functions. Arrow functions take away a lot of that hassle.