J'ai lu à plusieurs endroits que la principale différence est que "this
est lié lexicalement aux fonctions fléchées". C'est bien beau, mais je ne sais pas vraiment ce que cela signifie.
Je sais que cela signifie qu'il est unique dans les limites des accolades définissant le corps de la fonction, mais je ne pouvais pas réellement vous dire la sortie du code suivant, car je n'ai aucune idée de ce à quoi se réfère this
, sauf si c'est se référant à la fonction de flèche de graisse elle-même .... ce qui ne semble pas utile.
var testFunction = () => { console.log(this) };
testFunction();
Les fonctions fléchées capturent la valeur this
du contexte englobant
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the person object
}, 1000);
}
var p = new Person();
Ainsi, pour répondre directement à votre question, this
à l'intérieur de votre fonction de flèche aurait la même valeur qu'avant l'attribution de la fonction de flèche.
Afin de fournir une vue d'ensemble, je vais expliquer à la fois la liaison dynamique et lexicale.
this
fait référence à l'objet sur lequel la méthode est appelée. Ceci est une phrase à lire régulièrement sur SO. Mais ce n'est encore qu'une phrase, assez abstraite. Existe-t-il un modèle de code correspondant à cette phrase?
Oui il y a:
_const o = {
m() { console.log(this) }
}
// the important patterns: applying methods
o.m(); // logs o
o["m"](); // logs o
_
m
est une méthode car elle repose sur this
. o.m()
ou o["m"]()
signifie que m
est appliqué à o
. Ces modèles sont la traduction Javascript de notre célèbre phrase.
Il existe un autre modèle de code important auquel vous devez faire attention:
_"use strict";
const o = {
m() { console.log(this) }
}
// m is passed to f as a callback
function f(m) { m() }
// another important pattern: passing methods
f(o.m); // logs undefined
f(o["m"]); // logs undefined
_
Il est très similaire au modèle précédent, seules les parenthèses sont manquantes. Mais les conséquences sont considérables: lorsque vous passez m
à la fonction f
, vous extrayez m
de son objet/contexte o
. Il est maintenant déraciné et this
ne fait référence à rien (mode strict supposé).
Les fonctions fléchées n'ont pas leur propre liaison this
/super
/arguments
. Ils les héritent de leur portée lexicale parent:
_const toString = Object.prototype.toString;
const o = {
foo: () => console.log("window", toString.call(this)),
bar() {
const baz = () => console.log("o", toString.call(this));
baz();
}
}
o.foo() // logs window [object Window]
o.bar() // logs o [object Object]
_
Hormis la portée globale (Window
dans les navigateurs), seules les fonctions peuvent former une portée en Javascript (et _{}
_ blocs dans ES2015). Lorsque la fonction de flèche _o.foo
_ est appelée, il n'y a pas de fonction environnante dont baz
pourrait hériter de son this
. Par conséquent, il capture la liaison this
de la portée globale qui est liée à l'objet Window
.
Lorsque baz
est invoqué par _o.bar
_, la fonction flèche est entourée par _o.bar
_ (_o.bar
_ forme sa portée lexicale parent) et peut hériter de _o.bar
_'s this
. _o.bar
_ a été appelé sur o
et donc son this
est lié à o
.
J'espère que cette émission de code pourrait vous donner une idée plus claire. Fondamentalement, "ceci" dans la fonction flèche est la version contextuelle actuelle de "ceci". Voir le code:
// 'this' in normal function & arrow function
var this1 = {
number: 123,
logFunction: function () { console.log(this); },
logArrow: () => console.log(this)
};
this1.logFunction(); // Object { number: 123}
this1.logArrow(); // Window
La fonction flèche this
pointe vers le parent environnant dans Es6, ce qui signifie qu'elle ne s'étend pas comme les fonctions anonymes dans ES5 ...
C'est un moyen très utile d'éviter d'attribuer var self à ce qui est largement utilisé dans ES5 ...
Regardez l'exemple ci-dessous, affectant une fonction à l'intérieur d'un objet:
var checkThis = {
normalFunction: function () { console.log(this); },
arrowFunction: () => console.log(this)
};
checkThis.normalFunction(); //Object {}
checkThis.arrowFunction(); //Window {external: Object, chrome: Object, document: document, tmpDebug: "", j: 0…}
Vous pouvez essayer de le comprendre en suivant le chemin ci-dessous
// whatever here it is, function or fat arrow or literally object declare
// in short, a pair of curly braces should be appeared here, eg:
function f() {
// the 'this' here is the 'this' in fat arrow function below, they are
// bind together right here
// if 'this' is meaningful here, eg. this === awesomeObject is true
console.log(this) // [object awesomeObject]
let a = (...param) => {
// 'this is meaningful here too.
console.log(this) // [object awesomeObject]
}
donc 'ceci' dans la fonction flèche large n'est pas lié, ce qui signifie que vous ne pouvez rien lier à 'ceci' ici, .apply ne sera pas, .call ne sera pas, .bind ne le sera pas. 'ceci' dans la fonction de flèche grasse est lié lorsque vous écrivez le texte du code dans votre éditeur de texte. "ceci" dans la fonction de flèche grasse est littéralement significatif ici. Ce que votre code écrit ici dans l'éditeur de texte est ce que votre application y exécute en repl. Ce que 'ceci' est lié en gras ne changera jamais sauf si vous le changez dans l'éditeur de texte. Désolé pour ma piscine en anglais ...
La fonction flèche ne se lie jamais avec le mot clé this
var env = "globalOutside";
var checkThis = {env: "insideNewObject", arrowFunc: () => {
console.log("environment: ", this.env);
} }
checkThis.arrowFunc() // expected answer is environment: globalOutside
// Now General function
var env = "globalOutside";
var checkThis = {env: "insideNewObject", generalFunc: function() {
console.log("environment: ", this.env);
} }
checkThis.generalFunc() // expected answer is enviroment: insideNewObject
// Hence proving that arrow function never binds with 'this'
Dans un autre exemple, si vous cliquez sur le bouton d'âge ci-dessous
<script>
var person = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: function() {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
var person2 = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: () => {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
</script>
<input type=button onClick="alert(person2.age());" value="Age">
il lèvera une exception comme celle-ci
× Erreur JavaScript: TypeError non capturé: Impossible de lire la propriété "getFullYear" de non défini sur la ligne 18
Mais si vous changez la ligne de person2
return new Date().getFullYear() - this.dob.getFullYear();
à
return new Date().getFullYear() - person2.dob.getFullYear();
cela fonctionnera parce que cette portée a changé en personne2