js箭头函数和普通函数区别

js箭头函数和普通函数区别

实验环境:nodejs v12.16.1

  1. 箭头函数不能作为构造函数,而普通函数可以 在这里插入图片描述

  2. 箭头函数没有原型,而普通函数有
    在这里插入图片描述

  3. 箭头函数return可以省略语句块。(如果=>右边不是语句块,则代表return右边的表达式或对象)
    在这里插入图片描述

  4. 箭头函数不绑定arguments(注意:浏览器环境下获取箭头函数的arguments会报错),而普通函数argument绑定了参数列表对象
    在这里插入图片描述

  5. 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指向other
            return 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指向了other
            return f.call(other, n);
        },
        d: (n) => {
            let f = (n) => {
                // 分析如下:
                // f是箭头函数,因此f的this指向上层函数作用域d的this
                // 由于d也是箭头函数,由于d没有再上层的函数作用域了,因此d的this指向顶部this
                // 因此f的this指向顶部this
                return 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)); // 11
    
    console.log(`============接下来比较复杂,但是要搞清楚=========================`);
    
    // 分析:
    // o.a普通函数,因此bind把o.a的this指向pig
    // o.a里面的f的this指向o.a的调用方,因此f的this指向pig
    console.log(o.a.call(pig, 1)); // 81
    
    console.log(o.b.call(pig, 1)); // 81
    
    console.log(o.c.call(pig, 1)); // 21
    
    console.log(o.d.call(pig, 1)); // 31
    
    console.log(o.e.call(pig, 1)); // 21
    
    console.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
    
  6. 箭头函数内不能用yield且不能用作Generator函数,而普通函数可以。

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值