Maison  >  Article  >  interface Web  >  Quelle est la différence entre les fonctions fléchées et les fonctions ordinaires dans es6

Quelle est la différence entre les fonctions fléchées et les fonctions ordinaires dans es6

青灯夜游
青灯夜游original
2022-03-08 12:11:013901parcourir

Différences : 1. La définition de la fonction flèche est beaucoup plus simple, plus claire et plus rapide que la définition de la fonction ordinaire ; 2. La fonction flèche ne crée pas son propre ceci, mais la fonction ordinaire le fait ; utilisé comme constructeur.La fonction flèche peut être utilisée comme constructeur;4. La fonction flèche n'a pas ses propres arguments, mais la fonction flèche en a.

Quelle est la différence entre les fonctions fléchées et les fonctions ordinaires dans es6

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

La fonction Arrow est un point de test à haute fréquence dans les entretiens frontaux. La fonction Arrow est une API d'ES6, je pense que beaucoup de gens la connaissent. Parce que sa syntaxe est plus simple que les fonctions ordinaires, elle est profondément appréciée par tout le monde.

1. Syntaxe de base

ES6 permet l'utilisation de flèches => pour définir les fonctions de flèches. Pour la syntaxe spécifique, regardons un exemple simple : =>来定义箭头函数,具体语法,我们来看一个简单的例子:

// 箭头函数
let fun = (name) => {
    // 函数体
    return `Hello ${name} !`;
};

// 等同于
let fun = function (name) {
    // 函数体
    return `Hello ${name} !`;
};

可以看出,定义箭头函在数语法上要比普通函数简洁得多。箭头函数省去了function关键字,采用箭头=>来定义函数。函数的参数放在=>前面的括号中,函数体跟在=>后的花括号中。

关于箭头函数的参数:

如果箭头函数没有参数,直接写一个空括号即可。

如果箭头函数的参数只有一个,也可以省去包裹参数的括号。

如果箭头函数有多个参数,将参数依次用逗号(,)分隔,包裹在括号中即可。

// 没有参数
let fun1 = () => {
    console.log(111);
};

// 只有一个参数,可以省去参数括号
let fun2 = name => {
    console.log(`Hello ${name} !`)
};

// 有多个参数
let fun3 = (val1, val2, val3) => {
    return [val1, val2, val3];
};

关于箭头函数的函数体:

如果箭头函数的函数体只有一句代码,就是简单返回某个变量或者返回一个简单的JS表达式,可以省去函数体的大括号{ }。

let f = val => val;
// 等同于
let f = function (val) { return val };

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

如果箭头函数的函数体只有一句代码,就是返回一个对象,可以像下面这样写:

// 用小括号包裹要返回的对象,不报错
let getTempItem = id => ({ id: id, name: "Temp" });

// 但绝不能这样写,会报错。
// 因为对象的大括号会被解释为函数体的大括号
let getTempItem = id => { id: id, name: "Temp" };

如果箭头函数的函数体只有一条语句并且不需要返回值(最常见是调用一个函数),可以给这条语句前面加一个void关键字

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

箭头函数最常见的用处就是简化回调函数。

// 例子一
// 正常函数写法
[1,2,3].map(function (x) {
  return x * x;
});

// 箭头函数写法
[1,2,3].map(x => x * x);

// 例子二
// 正常函数写法
var result = [2, 5, 1, 4, 3].sort(function (a, b) {
  return a - b;
});

// 箭头函数写法
var result = [2, 5, 1, 4, 3].sort((a, b) => a - b);

二、箭头函数与普通函数的区别

1、语法更加简洁、清晰

从上面的基本语法示例中可以看出,箭头函数的定义要比普通函数定义简洁、清晰得多,很快捷。

2、箭头函数不会创建自己的this(重要!!深入理解!!)

我们先来看看MDN上对箭头函数this的解释。

箭头函数不会创建自己的this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this

箭头函数没有自己的this,它会捕获自己在定义时(注意,是定义时,不是调用时)所处的外层执行环境的this,并继承这个this值。所以,箭头函数中this的指向在它被定义的时候就已经确定了,之后永远不会改变。

来看个例子:

var id = 'Global';

function fun1() {
    // setTimeout中使用普通函数
    setTimeout(function(){
        console.log(this.id);
    }, 2000);
}

function fun2() {
    // setTimeout中使用箭头函数
    setTimeout(() => {
        console.log(this.id);
    }, 2000)
}

fun1.call({id: 'Obj'});     // 'Global'

fun2.call({id: 'Obj'});     // 'Obj'

上面这个例子,函数fun1中的setTimeout中使用普通函数,2秒后函数执行时,这时函数其实是在全局作用域执行的,所以this指向Window对象,this.id就指向全局变量id,所以输出'Global'。 但是函数fun2中的setTimeout中使用的是箭头函数,这个箭头函数的this在定义时就确定了,它继承了它外层fun2的执行环境中的this,而fun2调用时thiscall方法改变到了对象{id: 'Obj'}中,所以输出'Obj'

再来看另一个例子:

var id = 'GLOBAL';
var obj = {
  id: 'OBJ',
  a: function(){
    console.log(this.id);
  },
  b: () => {
    console.log(this.id);
  }
};

obj.a();    // 'OBJ'
obj.b();    // 'GLOBAL'

上面这个例子,对象obj的方法a使用普通函数定义的,普通函数作为对象的方法调用时,this指向它所属的对象。所以,this.id就是obj.id,所以输出'OBJ'。 但是方法b是使用箭头函数定义的,箭头函数中的this实际是继承的它定义时所处的全局执行环境中的this,所以指向Window对象,所以输出'GLOBAL'。(这里要注意,定义对象的大括号{}

var id = 'Global';
// 箭头函数定义在全局作用域
let fun1 = () => {
    console.log(this.id)
};

fun1();     // 'Global'
// this的指向不会改变,永远指向Window对象
fun1.call({id: 'Obj'});     // 'Global'
fun1.apply({id: 'Obj'});    // 'Global'
fun1.bind({id: 'Obj'})();   // 'Global'
Comme vous. Comme vous pouvez le voir, la définition des fonctions fléchées est beaucoup plus simple que les fonctions ordinaires en termes de syntaxe mathématique. La fonction flèche omet le mot-clé function et utilise la flèche => pour définir la fonction. Les paramètres de la fonction sont placés entre parenthèses avant =>, et le corps de la fonction est placé entre accolades après =>.

🎜🎜À propos des paramètres de la fonction flèche : 🎜🎜🎜🎜①🎜 Si la fonction flèche n'a pas de paramètres, écrivez simplement une parenthèse vide. 🎜🎜🎜②🎜 Si la fonction flèche n'a qu'un seul paramètre, vous pouvez également omettre les parenthèses entourant le paramètre. 🎜🎜🎜③🎜 Si la fonction flèche a plusieurs paramètres, séparez les paramètres par des virgules (,) et placez-les entre parenthèses. 🎜
let Fun = (name, age) => {
    this.name = name;
    this.age = age;
};

// 报错
let p = new Fun('cao', 24);
🎜🎜À propos du corps de la fonction flèche : 🎜🎜🎜🎜①🎜 Si le corps de la fonction flèche n'a qu'une seule ligne de code, qui renvoie simplement une variable ou une simple expression JS, les accolades du le corps de la fonction peut être omis { }. 🎜
// 例子一
let fun = (val) => {
    console.log(val);   // 111
    // 下面一行会报错
    // Uncaught ReferenceError: arguments is not defined
    // 因为外层全局环境没有arguments对象
    console.log(arguments); 
};
fun(111);

// 例子二
function outer(val1, val2) {
    let argOut = arguments;
    console.log(argOut);    // ①
    let fun = () => {
        let argIn = arguments;
        console.log(argIn);     // ②
        console.log(argOut === argIn);  // ③
    };
    fun();
}
outer(111, 222);
🎜🎜②🎜 Si le corps de la fonction flèche n'a qu'une seule instruction, qui doit renvoyer un objet, vous pouvez l'écrire comme ceci : 🎜
let sayHi = () => {
    console.log('Hello World !')
};
console.log(sayHi.prototype); // undefined
🎜🎜③🎜 Si le corps de la fonction flèche n'a qu'une seule instruction et n'a pas besoin de renvoyer de valeur (le plus courant est d'appeler une fonction), vous pouvez ajouter un mot-clé void devant cette instruction🎜rrreee🎜L'utilisation la plus courante des fonctions fléchées est de simplifier la fonction de rappel. 🎜rrreee🎜🎜🎜 2. La différence entre les fonctions fléchées et les fonctions ordinaires 🎜🎜🎜🎜🎜 1. La syntaxe est plus concise et claire 🎜🎜🎜 Comme le montrent les exemples de syntaxe de base ci-dessus, la définition des fonctions fléchées est plus simple que la définition des fonctions ordinaires, beaucoup plus claire et plus rapide. 🎜🎜🎜2. La fonction flèche ne crée pas son propre this (Important !! Compréhension approfondie !!) 🎜🎜🎜 Jetons d'abord un coup d'œil à l'explication de la fonction flèche this sur MDN. . 🎜🎜🎜La fonction flèche ne crée pas son propre this, elle n'a donc pas son propre this, elle héritera uniquement du de son propre niveau supérieur chaîne de portée ceci. 🎜🎜🎜La fonction flèche n'a pas son propre this, elle capturera le this de l'environnement d'exécution externe où il se trouve lors de la 🎜définition🎜 (attention, lorsqu'il est défini, pas lorsqu'il est appelé) 🎜, et hérite de cette cette valeur. Par conséquent, le pointage de this dans la fonction flèche est déterminé lors de sa définition, et ne changera jamais par la suite. 🎜🎜Regardons un exemple : 🎜rrreee🎜Dans l'exemple ci-dessus, une fonction normale est utilisée dans setTimeout dans la fonction fun1 lorsque la fonction est exécutée après 2. secondes, la fonction est en fait exécutée dans la portée globale, donc this pointe vers l'objet Window et this.id pointe vers l'objet variable globale id. Donc, affichez 'Global'. Mais la fonction flèche est utilisée dans setTimeout dans la fonction fun2. Le this de cette fonction flèche est déterminé lorsqu'elle est définie, et elle en hérite. . this dans l'environnement d'exécution du fun2 externe, et lorsque fun2 est appelé, this est . appelée La méthode code> est remplacée par l'objet <code>{id: 'Obj'>, donc 'Obj' est affiché. 🎜🎜Regardons un autre exemple : 🎜rrreee🎜Dans l'exemple ci-dessus, la méthode a de l'objet obj est définie à l'aide d'une fonction ordinaire 🎜Lorsque la fonction ordinaire est. appelé comme méthode de l'objet, this pointe vers l'objet auquel il appartient 🎜. Par conséquent, this.id est obj.id, donc 'OBJ' est affiché. Cependant, la méthode b est définie à l'aide d'une fonction flèche. this dans la fonction flèche hérite en fait de thisdans l'environnement d'exécution global où elle est définie. >, donc il pointe vers l'objet Window, donc 'GLOBAL' est affiché. (🎜Il est à noter ici que les accolades {} qui définissent l'objet ne peuvent pas former un environnement d'exécution séparé, il est toujours dans l'environnement d'exécution global !!🎜)🎜

3、箭头函数继承而来的this指向永远不变(重要!!深入理解!!)

上面的例子,就完全可以说明箭头函数继承而来的this指向永远不变。对象obj的方法b是使用箭头函数定义的,这个函数中的this永远指向它定义时所处的全局执行环境中的this,即便这个函数是作为对象obj的方法调用,this依旧指向Window对象。

4、.call()/.apply()/.bind()无法改变箭头函数中this的指向

.call()/.apply()/.bind()方法可以用来动态修改函数执行时this的指向,但由于箭头函数的this定义时就已经确定且永远不会改变。所以使用这些方法永远也改变不了箭头函数this的指向,虽然这么做代码不会报错。

var id = &#39;Global&#39;;
// 箭头函数定义在全局作用域
let fun1 = () => {
    console.log(this.id)
};

fun1();     // &#39;Global&#39;
// this的指向不会改变,永远指向Window对象
fun1.call({id: &#39;Obj&#39;});     // &#39;Global&#39;
fun1.apply({id: &#39;Obj&#39;});    // &#39;Global&#39;
fun1.bind({id: &#39;Obj&#39;})();   // &#39;Global&#39;

5、箭头函数不能作为构造函数使用

我们先了解一下构造函数的new都做了些什么?简单来说,分为四步: ① JS内部首先会先生成一个对象; ② 再把函数中的this指向该对象; ③ 然后执行构造函数中的语句; ④ 最终返回该对象实例。

但是!!因为箭头函数没有自己的this,它的this其实是继承了外层执行环境中的this,且this指向永远不会随在哪里调用、被谁调用而改变,所以箭头函数不能作为构造函数使用,或者说构造函数不能定义成箭头函数,否则用new调用时会报错!

let Fun = (name, age) => {
    this.name = name;
    this.age = age;
};

// 报错
let p = new Fun(&#39;cao&#39;, 24);

6、箭头函数没有自己的arguments

箭头函数没有自己的arguments对象。在箭头函数中访问arguments实际上获得的是外层局部(函数)执行环境中的值。

// 例子一
let fun = (val) => {
    console.log(val);   // 111
    // 下面一行会报错
    // Uncaught ReferenceError: arguments is not defined
    // 因为外层全局环境没有arguments对象
    console.log(arguments); 
};
fun(111);

// 例子二
function outer(val1, val2) {
    let argOut = arguments;
    console.log(argOut);    // ①
    let fun = () => {
        let argIn = arguments;
        console.log(argIn);     // ②
        console.log(argOut === argIn);  // ③
    };
    fun();
}
outer(111, 222);

上面例子二,①②③处的输出结果如下:

Quelle est la différence entre les fonctions fléchées et les fonctions ordinaires dans es6

很明显,普通函数outer内部的箭头函数fun中的arguments对象,其实是沿作用域链向上访问的外层outer函数的arguments对象。

可以在箭头函数中使用rest参数代替arguments对象,来访问箭头函数的参数列表!!

7、箭头函数没有原型prototype

let sayHi = () => {
    console.log(&#39;Hello World !&#39;)
};
console.log(sayHi.prototype); // undefined

8、箭头函数不能用作Generator函数,不能使用yeild关键字

【相关推荐:javascript视频教程web前端

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