Maison  >  Article  >  interface Web  >  La fonction es6 arrow est-elle une programmation fonctionnelle ?

La fonction es6 arrow est-elle une programmation fonctionnelle ?

青灯夜游
青灯夜游original
2023-01-11 17:15:401497parcourir

Oui. Les fonctions fléchées sont une manifestation de la programmation fonctionnelle. La programmation fonctionnelle se concentre davantage sur la relation entre l'entrée et la sortie, en omettant certains facteurs dans le processus. Par conséquent, les fonctions fléchées n'ont pas leur propre ceci, leurs arguments et leur nouvelle cible ( ES6) et super (. ES6); les fonctions fléchées sont équivalentes aux fonctions anonymes, donc new ne peut pas être utilisé comme constructeur.

La fonction es6 arrow est-elle une programmation fonctionnelle ?

L'environnement d'exploitation de ce tutoriel : système Windows 7, ECMAScript version 6, ordinateur Dell G3.

Fonction flèche

La fonction flèche est une nouvelle fonctionnalité introduite dans ES6, qui utilise la "flèche" (=>) pour définir des fonctions.

var f = v => v;
// 等同于
var f = function (v) {
  return v;
};

Si la fonction flèche ne nécessite aucun paramètre ou nécessite plusieurs paramètres, utilisez une parenthèse pour représenter la partie paramètre.

var f = () => 5;
// 等同于
var f = function () { return 5 };
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};

Si le bloc de code de la fonction fléchée contient plus d'une instruction, utilisez des accolades pour les entourer et utilisez l'instruction return pour revenir.

var sum = (num1, num2) => { return num1 + num2; }

Étant donné que les accolades sont interprétées comme des blocs de code, si la fonction flèche renvoie directement un objet, vous devez ajouter des parenthèses à l'extérieur de l'objet, sinon une erreur sera signalée.

// 报错
let getTempItem = id => { id: id, name: "Temp" };
// 不报错
let getTempItem = id => ({ id: id, name: "Temp" });

Ce qui suit est un cas particulier, même si cela fonctionnera, vous obtiendrez de mauvais résultats.

let foo = () => { a: 1 };
foo() // undefined

Dans le code ci-dessus, l'intention initiale est de renvoyer un objet { a: 1 }, mais parce que le moteur pense que les accolades sont des blocs de code, une ligne d'instruction a: 1 est exécutée. À ce stade, a peut être interprété comme l'étiquette de l'instruction, donc l'instruction réellement exécutée est 1 ;, puis la fonction se termine sans valeur de retour.

Si la fonction flèche n'a qu'une seule ligne d'instructions et n'a pas besoin de renvoyer de valeur, vous pouvez utiliser la méthode d'écriture suivante sans écrire d'accolades.

let fn = () => void doesNotReturn();

Explication :

La fonction flèche est une manifestation de la programmation fonctionnelle La programmation fonctionnelle se concentre davantage sur la relation entre l'entrée et la sortie, en omettant certains facteurs du processus, donc dans la fonction flèche Elle n'a pas son propre ceci. , arguments, nouvelle cible (ES6) et super (ES6). Les fonctions fléchées sont équivalentes aux fonctions anonymes, donc new ne peut pas être utilisé comme constructeur.

Ceci dans une fonction fléchée pointe toujours vers cela dans sa portée parent. En d’autres termes, la fonction flèche capture la valeur this du contexte dans lequel elle se trouve comme sa propre valeur this. Son pointeur ne peut être modifié par aucune méthode, telle que call(), bind(), apply(). Lors de l'appel de ceci dans une fonction fléchée, il recherche simplement la chaîne de portées pour trouver le this le plus proche et l'utilise. Cela n'a rien à voir avec le contexte de l'appel. Expliquons-le en utilisant du code.

Les fonctions fléchées peuvent être utilisées conjointement avec la déstructuration de variables

const full = ({ first, last }) => first + ' ' + last;
// 等同于
function full(person) {
  return person.first + ' ' + person.last;
}

Les fonctions fléchées rendent les expressions plus concises

const isEven = n => n % 2 === 0;
const square = n => n * n;

Le code ci-dessus utilise seulement deux lignes pour définir deux fonctions utilitaires simples. Si les fonctions fléchées n’étaient pas utilisées, cela pourrait occuper plusieurs lignes et ne serait pas aussi accrocheur qu’aujourd’hui.

Une utilisation des fonctions fléchées consiste à simplifier les fonctions de rappel

// 正常函数写法
[1,2,3].map(function (x) {
  return x * x;
});
// 箭头函数写法
[1,2,3].map(x => x * x);

Un autre exemple est

// 正常函数写法
var result = values.sort(function (a, b) {
  return a - b;
});
// 箭头函数写法
var result = values.sort((a, b) => a - b);

Ce qui suit est un exemple de combinaison du paramètre rest avec la fonction flèche.

const numbers = (...nums) => nums;
numbers(1, 2, 3, 4, 5)
// [1,2,3,4,5]
const headAndTail = (head, ...tail) => [head, tail];
headAndTail(1, 2, 3, 4, 5)
// [1,[2,3,4,5]]

Points à noter lors de l'utilisation

Il y a plusieurs points à noter lors de l'utilisation des fonctions fléchées.

(1) L'objet this dans le corps de la fonction est l'objet où il est défini, pas l'objet où il est utilisé.

(2) ne peut pas être utilisé comme constructeur, c'est-à-dire que la nouvelle commande ne peut pas être utilisée, sinon une erreur sera générée.

(3) L'objet arguments ne peut pas être utilisé, car l'objet n'existe pas dans le corps de la fonction. Si vous souhaitez l'utiliser, vous pouvez utiliser le paramètre rest à la place.

(4) La commande rendement ne peut pas être utilisée, donc les fonctions fléchées ne peuvent pas être utilisées comme fonctions générateur.

Parmi les quatre points ci-dessus, le premier point est particulièrement remarquable. Le pointeur de cet objet est variable, mais dans une fonction flèche, il est fixe.

function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}
var id = 21;
foo.call({ id: 42 });
// id: 42

Dans le code ci-dessus, le paramètre de setTimeout est une fonction de flèche. La définition de cette fonction de flèche prend effet lorsque la fonction foo est générée, et son exécution réelle n'attendra que 100 millisecondes plus tard. S'il s'agit d'une fonction normale, elle devrait pointer vers la fenêtre de l'objet global lors de son exécution, et 21 devrait être affiché à ce moment-là. Cependant, la fonction flèche fait que cela pointe toujours vers l'objet où la définition de la fonction prend effet (dans ce cas, {id : 42}), donc la sortie est 42.

La fonction de flèche permet à cela dans setTimeout d'être lié à la portée où il est défini, plutôt que de pointer vers la portée où il est exécuté. Voici un autre exemple.

function Timer() {
  this.s1 = 0;
  this.s2 = 0;
  // 箭头函数
  setInterval(() => this.s1++, 1000);
  // 普通函数
  setInterval(function () {
    this.s2++;
  }, 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0

Dans le code ci-dessus, deux minuteries sont configurées à l'intérieur de la fonction Timer, en utilisant respectivement les fonctions fléchées et les fonctions ordinaires. La liaison this du premier est définie dans la portée (c'est-à-dire la fonction Timer), et celle du second pointe vers la portée dans laquelle elle est exécutée (c'est-à-dire l'objet global). Ainsi, après 3 100 millisecondes, timer.s1 a été mis à jour trois fois, mais timer.s2 n'a pas été mis à jour une seule fois.

La fonction flèche peut corriger ce point. Cette fonctionnalité est très utile pour encapsuler les fonctions de rappel. Vous trouverez ci-dessous un exemple où la fonction de rappel d'un événement DOM est encapsulée dans un objet.

var handler = {
  id: '123456',
  init: function() {
    document.addEventListener('click',
      event => this.doSomething(event.type), false);
  },
  doSomething: function(type) {
    console.log('Handling ' + type  + ' for ' + this.id);
  }
};

Dans la méthode init du code ci-dessus, une fonction de flèche est utilisée, ce qui fait que celle-ci dans la fonction de flèche pointe toujours vers l'objet gestionnaire. Sinon, lorsque la fonction de rappel s'exécute, la ligne this.doSomething signalera une erreur, car elle pointe vers l'objet document à ce moment-là.

this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。

所以,箭头函数转成 ES5 的代码如下。

// ES6
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}
// ES5
function foo() {
  var _this = this;
  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}

上面代码中,转换后的 ES5 版本清楚地说明了,箭头函数里面根本没有自己的this,而是引用外层的this。

请问下面的代码之中有几个this?

function foo() {
  return () => {
    return () => {
      return () => {
        console.log('id:', this.id);
      };
    };
  };
}
var f = foo.call({id: 1});
var t1 = f.call({id: 2})()(); // id: 1
var t2 = f().call({id: 3})(); // id: 1
var t3 = f()().call({id: 4}); // id: 1

上面代码之中,只有一个this,就是函数foo的this,所以t1、t2、t3都输出同样的结果。因为所有的内层函数都是箭头函数,都没有自己的this,它们的this其实都是最外层foo函数的this。

除了this,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:arguments、super、new.target。

function foo() {
  setTimeout(() => {
    console.log('args:', arguments);
  }, 100);
}
foo(2, 4, 6, 8)
// args: [2, 4, 6, 8]

上面代码中,箭头函数内部的变量arguments,其实是函数foo的arguments变量。

另外,由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。

(function() {
  return [
    (() => this.x).bind({ x: 'inner' })()
  ];
}).call({ x: 'outer' });
// ['outer']

上面代码中,箭头函数没有自己的this,所以bind方法无效,内部的this指向外部的this。

长期以来,JavaScript 语言的this对象一直是一个令人头痛的问题,在对象方法中使用this,必须非常小心。箭头函数”绑定”this,很大程度上解决了这个困扰。

【相关推荐:javascript视频教程编程视频

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn