No lexical this

An arrow function does not have its own this. Unlike an ES5 function, that will create a separate execution context of its own, an arrow function uses surrounding execution context. Let's see the following shopping cart example:

1.  var shoppingCart = {
2. items: ['Apple', 'Orange'],
3. inventory: {Apple: 1, Orange: 0},
4. checkout () {
5. this.items.forEach(item => {
6. if (!this.inventory[item]) {
7. console.log('Item ' + item + ' has sold out.');
8. }
9. })
10. }
11. }
12. shoppingCart.checkout();
13.
14. // equivalent to ES5
15. var shoppingCart = {
16. items: ['Apple', 'Orange'],
17. inventory: {Apple: 1, Orange: 0},
18. checkout: function () {
19. // Reassign context and use closure to make it
20. // visible to the callback passed to forEach
21. var that = this
22. this.items.forEach(function(item){
23. if (!that.inventory[item]) {
24. console.log('Item ' + item + ' has sold out.');
25. }
26. })
27. }
28. }
29. shoppingCart.checkout();

In line 6, this refers to the shoppingCart object itself, even it is inside the callback of the Array.prototype.forEach() method. As you can see in line 21, with the ES5 version, you need to use closure to keep the execution context available to the callback function.

And because an arrow function does not have a separate execution context, when it is invoked with Function.prototype.call(), Function.prototype.apply(), or Function.prototype.bind() method, the execution context that passed in as the first argument will be ignored. Let's take a look at an example:

1. var name = 'Unknown';
2. var greeting = () => {
3. console.log('Hi, I'm ' + this.name);
4. };
5. greeting.call({name: 'Sunny'}); // I'm Unknown
6. greeting.apply({name: 'Tod'}); // I'm Unknown
7. var newGreeting = greeting.bind({name: 'James'});
8. newGreeting(); // I'm Unknown

As you can see from line 3, in an arrow function, this always resolves to its surrounding execution context. The call(), apply(), or bind() method has no effect on its execution context.

Unlike ES5 functions, arrow functions do not have their own arguments object. The arguments object is a reference to the surrounding function's arguments object.

Because arrow functions use its surrounding execution context, they are not suitable for defining methods of objects. 

Let's see the following shopping cart example, which uses an arrow function for the checkout:

1.  var shoppingCart = {
2. items: ['Apple', 'Orange'],
3. inventory: {Apple: 1, Orange: 0},
4. checkout: () => {
5. this.items.forEach(item => {
6. if (!this.inventory[item]) {
7. console.log('Item ' + item + ' has sold out.');
8. }
9. })
10. }
11. }
12. shoppingCart.checkout();

In line 4, we change checkout to an arrow function. And because an arrow function uses its surrounding execution context, this in line 5 no longer references the shoppingCart object and it will throw Uncaught TypeError: Cannot read property 'forEach' of undefined.

The preceding shopping cart example is written with object literals. Arrow functions do not work well when defining object methods using a prototype object either. Let's see the following example:

1.  class User {
2. constructor(name) {
3. this.name = name;
4. }
5. }
6. User.prototype.swim = () => {
7. console.log(this.name + ' is swimming');
8. };
9. var user = new User();
10. console.log(user.swim()); // is swimming

As you can see from the output, in line 7this does not reference the user object. In this example, it references the global context.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.163.13