Apprenez ES6 The Dope Way Partie II: Fonctions fléchées et mot-clé 'this'

Bienvenue dans la partie II de Learn ES6 The Dope Way, une série créée pour vous aider à comprendre facilement ES6 (ECMAScript 6)!

Alors, qu'est-ce que c'est => ; ?

Vous avez probablement vu ces étranges symboles hiéroglyphiques à l'aspect égyptien ici et là, en particulier dans le code de quelqu'un d'autre, où vous déboguez actuellement un problème de mot-clé « this» . Après une heure de bricolage, vous parcourez maintenant la barre de recherche Google et traquez Stack Overflow. Semble familier?

Ensemble, couvrons trois sujets dans Learn ES6 The Dope Way Part II:

  • Comment le mot-clé « this » se rapporte à => .
  • Comment migrer des fonctions d'ES5 vers ES6.
  • Remarques importantes à prendre en compte lors de l'utilisation de => .

Fonctions fléchées

Les fonctions fléchées ont été créées pour simplifier la portée des fonctions et rendre l'utilisation du mot-clé « this » beaucoup plus simple. Ils utilisent le = & gt; syntaxe, qui ressemble à une flèche. Même si je ne pense pas qu'il soit nécessaire de suivre un régime, les gens l'appellent «la grosse flèche» (et les amateurs de Ruby la connaissent peut-être mieux sous le nom de «hash rock et») - quelque chose dont il faut être conscient.

Lien entre le mot-clé "this" et les fonctions fléchées

Avant de plonger plus profondément dans les fonctions fléchées ES6, il est important d'avoir d'abord une image claire de ce à quoi « cela » se lie dans le code ES5.

Si le mot-clé « this » était à l'intérieur de la méthode d' un objet (une fonction qui appartient à un objet), à quoi ferait-il référence?

// Test it here: //jsfiddle.net/maasha/x7wz1686/ var bunny = { name: 'Usagi', showName: function() { alert(this.name); } }; bunny.showName(); // Usagi

Correct! Cela ferait référence à l'objet. Nous verrons pourquoi plus tard.

Et si le mot-clé « this » était à l'intérieur de la fonction de la méthode?

// Test it here: //jsfiddle.net/maasha/z65c1znn/ var bunny = { name: 'Usagi', tasks: ['transform', 'eat cake', 'blow kisses'], showTasks: function() { this.tasks.forEach(function(task) { alert(this.name + " wants to " + task); }); } }; bunny.showTasks(); // [object Window] wants to transform // [object Window] wants to eat cake // [object Window] wants to blow kisses // please note, in jsfiddle the [object Window] is named 'result' within inner functions of methods. 

Qu'est-ce que vous obtenez? Attends, qu'est-il arrivé à notre lapin…?

Ah, pensez-vous que « ceci » fait référence à la fonction interne de la méthode?

Peut-être l'objet lui-même?

Vous êtes sage de le penser, mais ce n'est pas le cas. Permettez-moi de vous apprendre ce que les anciens du codage m'avaient appris une fois:

Codage Elder : « Ah oui, t - il le code est fort avec celui - ci. Il est en effet pratique de penser que « ceci » se fixe par mot - clé à la fonction , mais la vérité est, « ce » est maintenant tombé hors de portée ... Il appartient maintenant ... », il fait une pause comme si l' expérience trouble intérieur , « l'objet de la fenêtre . "

C'est vrai. C'est exactement comme ça que ça s'est passé.

Pourquoi « this » est-il lié à l'objet window? Parce que ' this ' fait toujours référence au propriétaire de la fonction dans laquelle il se trouve, dans ce cas - puisqu'il est maintenant hors de portée - la fenêtre / l'objet global.

Lorsqu'il est à l'intérieur de la méthode d'un objet, le propriétaire de la fonction est l'objet. Ainsi, le mot-clé « this » est lié à l'objet. Pourtant, quand il est à l'intérieur d'une fonction, soit autonome ou dans une autre méthode, il fera toujours référence à l'objet window / global.

// Test it here: //jsfiddle.net/maasha/g278gjtn/ var standAloneFunc = function(){ alert(this); } standAloneFunc(); // [object Window]

Mais pourquoi…?

Ceci est connu comme une bizarrerie JavaScript, ce qui signifie quelque chose qui se produit simplement dans JavaScript qui n'est pas vraiment simple et qui ne fonctionne pas comme vous le pensez. Cela a également été considéré par les développeurs comme un mauvais choix de conception, auquel ils remédient maintenant avec les fonctions fléchées d'ES6.

Avant de continuer, il est important de connaître deux façons intelligentes que les programmeurs résolvent le problème `` ce '' dans le code ES5, d'autant plus que vous continuerez à utiliser ES5 pendant un certain temps (tous les navigateurs n'ont pas encore complètement migré vers ES6):

# 1 Créez une variable en dehors de la fonction interne de la méthode. Maintenant, la méthode 'forEach' accède à ' this ' et donc aux propriétés de l'objet et à leurs valeurs. Ceci est dû au fait que « this » est stocké dans une variable alors qu'il est toujours dans la portée de la méthode directe de l'objet «showTasks».

// Test it here: //jsfiddle.net/maasha/3mu5r6vg/ var bunny = { name: 'Usagi', tasks: ['transform', 'eat cake', 'blow kisses'], showTasks: function() { var _this = this; this.tasks.forEach(function(task) { alert(_this.name + " wants to " + task); }); } }; bunny.showTasks(); // Usagi wants to transform // Usagi wants to eat cake // Usagi wants to blow kisses

# 2 Utilisez bind pour attacher le mot-clé ' this ' qui fait référence à la méthode à la fonction interne de la méthode.

// Test it here: //jsfiddle.net/maasha/u8ybgwd5/ var bunny = { name: 'Usagi', tasks: ['transform', 'eat cake', 'blow kisses'], showTasks: function() { this.tasks.forEach(function(task) { alert(this.name + " wants to " + task); }.bind(this)); } }; bunny.showTasks(); // Usagi wants to transform // Usagi wants to eat cake // Usagi wants to blow kisses

Et voici maintenant… les fonctions Arrow! Traiter ce problème n'a jamais été aussi simple et simple! La solution ES6 simple:

// Test it here: //jsfiddle.net/maasha/che8m4c1/ var bunny = { name: 'Usagi', tasks: ['transform', 'eat cake', 'blow kisses'], showTasks() { this.tasks.forEach((task) => { alert(this.name + " wants to " + task); }); } }; bunny.showTasks(); // Usagi wants to transform // Usagi wants to eat cake // Usagi wants to blow kisses

Alors que dans ES5, « ceci » fait référence au parent de la fonction, dans ES6, les fonctions fléchées utilisent une portée lexicale - « ceci » fait référence à sa portée environnante actuelle et pas plus. Ainsi, la fonction intérieure savait se lier uniquement à la fonction intérieure, et non à la méthode de l'objet ou à l'objet lui-même.

Comment migrer des fonctions d'ES5 vers ES6.

// Before let bunny = function(name) { console.log("Usagi"); } // After let bunny = (name) => console.log("Usagi") // Step 1: Remove the word ‘function’. let bunny = (name) { console.log("Usagi"); } // Step 2: If your code is less than a line, remove brackets and place on one line. let bunny = (name) console.log("Usagi"); // Step 3. Add the hash rocket. let bunny = (name) => console.log("Usagi");

Tu l'as fait! Bon travail! Assez simple, non? Voici quelques autres exemples utilisant la grosse flèche maigre, pour habituer vos yeux:

// #1 ES6: if passing one argument you don't need to include parenthesis around parameter. var kitty = name => name; // same as ES5: var kitty = function(name) { return name; }; // #2 ES6: no parameters example. var add = () => 3 + 2; // same as ES5: var add = function() { return 3 + 2; }; // #3 ES6: if function consists of more than one line or is an object, include braces. var objLiteral = age => ({ name: "Usagi", age: age }); // same as ES5: var objLiteral = function(age) { return { name: "Usagi", age: age }; }; // #4 ES6: promises and callbacks. asyncfn1().then(() => asyncfn2()).then(() => asyncfn3()).then(() => done()); // same as ES5: asyncfn1().then(function() { asyncfn2(); }).then(function() { asyncfn3(); }).done(function() { done(); });

Remarques importantes à prendre en compte lors de l'utilisation des fonctions Flèche

Si vous utilisez le mot-clé 'new' avec les fonctions =>, une erreur sera générée. Les fonctions fléchées ne peuvent pas être utilisées comme constructeur - les fonctions normales supportent le «nouveau» via le prototype de propriété et la méthode interne [[Construct]]. Les fonctions fléchées n'utilisent ni l'un ni l'autre, donc le nouveau (() => {}) renvoie une erreur.

Autres bizarreries à considérer:

// Line breaks are not allowed and will throw a syntax error let func1 = (x, y) => { return x + y; }; // SyntaxError // But line breaks inside of a parameter definition is ok let func6 = ( x, y ) => { return x + y; }; // Works! // If an expression is the body of an arrow function, you don’t need braces: asyncFunc.then(x => console.log(x)); // However, statements have to be put in braces: asyncFunc.catch(x => { throw x }); // Arrow functions are always anonymous which means you can’t just declare them as in ES5: function squirrelLife() { // play with squirrels, burrow for food, etc. } // Must be inside of a variable or object property to work properly: let squirrelLife = () => { // play with squirrels, burrow for food, etc. // another super squirrel action. }

Félicitations! Vous avez réussi à apprendre ES6 The Dope Way Part II et maintenant vous avez une base pour la connaissance de la fonction de flèche, les avantages lexicaux que cela donne à `` ceci '' et vous avez également acquis des compétences excentriques en JavaScript! :)

Gardez votre sagesse à jour en aimant et en suivant au fur et à mesure. En savoir plus ES6 The Dope Way arrive bientôt sur Medium!

Partie I: const, let & var

Partie II: (Flèche) => fonctions et mot-clé 'this'

Part III: Template Literals, Spread Operators & Generators!

Part IV: Default Parameters, Destructuring Assignment, and a new ES6 method!

Part V: Classes, Transpiling ES6 Code & More Resources!

You can also find me on github ❤ //github.com/Mashadim