js箭头函数和普通函数区别
实验环境:nodejs v12.16.1
-
箭头函数不能作为构造函数,而普通函数可以
-
箭头函数没有原型,而普通函数有
-
箭头函数return可以省略语句块。(如果=>右边不是语句块,则代表return右边的表达式或对象)
-
箭头函数不绑定arguments(注意:浏览器环境下获取箭头函数的arguments会报错),而普通函数argument绑定了参数列表对象
-
this指向问题[重点,也是难点]
- 箭头函数的this指向上层函数作用域的this对象,如果没有上层函数作用域,则指向顶部this(在浏览器中顶部this则是window)。普通函数的this指向该函数的调用者。
- call, apply, bind会改变普通函数的this,但不会改变箭头函数的this
实践是检验真理的有效标准,在此,我们必须更加深入了解,再耐心看一个复杂的例子:
依然是nodejs环境下:
data = 40; // 全局作用域赋予data=40 this.data = 30; // 给顶部this赋予data=30 let pig = {data: 80, }; let o = {data: 10,a(n) {let f = (n) => {// 分析如下:// 首先f是箭头函数,那么f的this指向上层函数作用域的this,f的上层函数作用域是a,因此f的this指向a的this// 由于a是普通函数,因此a的this指向a的调用方// 因此f的this指向a的调用方return n + this.data;};return f(n);},b(n) {let f = (n) => {return n + this.data;};let other = {data: 20,};// 分析如下:// 和函数a的情形分析一样,这里的f的this指向是b的调用方// 然而 call,bind,apply 并不会改变箭头函数的调用方,因此f.call(other, n)并不会把this指向otherreturn f.call(other, n);},c(n) {let f = function (n) {// 分析如下:// f是普通函数,因此f的this指向f的调用方return n + this.data;};let other = {data: 20,};// 分析如下:// call会改变普通函数的调用方,因此f.call(other, n)把this指向了otherreturn f.call(other, n);},d: (n) => {let f = (n) => {// 分析如下:// f是箭头函数,因此f的this指向上层函数作用域d的this// 由于d也是箭头函数,由于d没有再上层的函数作用域了,因此d的this指向顶部this// 因此f的this指向顶部thisreturn n + this.data;};return f(n);},e(n) {let f = function (n) {return n + this.data;};let other = {data: 20,};// g的this指向other了let g = f.bind(other);return g(n);},e1(n) {let f = function (n) {return n + this.data;};// 注意,nodejs下这里f的调用方是global(注意nodejs下的顶层this并不等于global,顶层this是当前模块的this)return f(n);},e2(n) {let f = (n) => {return n + this.data;};let other = {data: 20,};// bind对箭头函数不起作用,f的this -> e2的this -> e2的调用方let g = f.bind(other);return g(n);}, };console.log(o.a(1)); // 11 console.log(o.b(1)); // 11 console.log(o.c(1)); // 21 console.log(o.d(1)); // 31 console.log(o.e(1)); // 21 console.log(o.e1(1)); // 41 console.log(o.e2(1)); // 11console.log(`============接下来比较复杂,但是要搞清楚=========================`);// 分析: // o.a普通函数,因此bind把o.a的this指向pig // o.a里面的f的this指向o.a的调用方,因此f的this指向pig console.log(o.a.call(pig, 1)); // 81console.log(o.b.call(pig, 1)); // 81console.log(o.c.call(pig, 1)); // 21console.log(o.d.call(pig, 1)); // 31console.log(o.e.call(pig, 1)); // 21console.log(o.e1.call(pig, 1)); // 41// 分析 // o.e2普通函数,因此bind把o.e2的this指向pig // o.e2里面的f是箭头函数,因此f指向上层函数作用域o.e2的this,而o.e2的this指向了pig,因此f的this指向pig // o.e2里面的f是箭头函数,不会被bind改变指向,因此g的this也指向pig console.log(o.e2.call(pig, 1)); // 81
-
箭头函数内不能用yield且不能用作Generator函数,而普通函数可以。