web-dev-qa-db-fra.com

À quoi "ceci" fait-il référence dans les fonctions fléchées d'ES6?

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();
45
temporary_user_name

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.

35
dave

Afin de fournir une vue d'ensemble, je vais expliquer à la fois la liaison dynamique et lexicale.

Liaison de nom dynamique

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é).

Liaison de noms lexicaux (ou statiques)

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.

16
user6445533

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 
3
Xin

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…}
2
Alireza

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 ...

1
Plasmatium

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'
0
TrickOrTreat

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

0
Hamit YILDIRIM