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函数,而普通函数可以。

<think>嗯,用户想了解JavaScript箭头函数普通函数区别。之前已经回答过Vue2Vue3的区别,现在需要根据提供的引用来组织答案。首先,我需要回顾用户提供的四个引用内容,确保涵盖所有提到的区别点。 引用[1]提到语法简洁性一些示例代码,引用[2]补充了函数表达式箭头函数的对比,引用[3]强调了this指向的不同,引用[4]详细说明了this的指向问题以及简写方式。用户的问题明确,需要结构化回答,可能包括语法、this绑定、构造函数、arguments对象、方法适用场景等。 需要确保每个部分都有对应的引用标注,比如语法部分来自引用1、3,this指向来自3、4。同时要注意用户之前的问题是关于Vue的,但这次是纯JavaScript的问题,可能需要更基础的解释,但用户可能有一定的前端背景,所以可以适当深入。 可能用户还想知道在实际开发中何时使用箭头函数,何时使用普通函数,比如在Vue的方法定义或者回调函数中的选择,但根据引用内容,没有提到Vue相关,所以暂时专注于核心区别。需要检查是否有遗漏点,比如super、new.target或者原型属性,但引用中没有提到这些,可能不需要涉及。 最后,生成相关问题时要围绕已讨论的内容,比如this的应用场景、如何选择等。确保回答符合格式要求,使用中文,正确引用,分点清晰,代码示例正确使用$...$格式。</think>### JavaScript箭头函数普通函数区别 --- #### 1. **语法简洁性** - **箭头函数**:使用`=>`语法,省略`function`关键字,单行代码可隐式返回(无需`return`)[^1][^3]。 ```javascript // 普通函数 function add(a, b) { return a + b; } // 箭头函数 const add = (a, b) => a + b; // 省略{}return ``` 若参数唯一,可省略括号: ```javascript const square = x => x * x; ``` - **普通函数**:需显式声明`function`,返回值必须用`return`。 --- #### 2. **this指向(核心区别)** - **普通函数**: `this`指向**调用时的上下文**(动态绑定),例如: - 作为对象方法:`this`指向调用对象[^4]。 - 作为构造函数:`this`指向实例对象。 - 未明确调用者时:非严格模式下指向`window`(浏览器环境),严格模式下为`undefined`。 ```javascript const obj = { name: "Alice", greet: function() { console.log(this.name); // 输出"Alice" } }; obj.greet(); ``` - **箭头函数**: **无自身`this`**,继承**定义时所在作用域的`this`**(词法绑定)[^3]。 ```javascript const obj = { name: "Alice", greet: () => { console.log(this.name); // 输出undefined(外层无定义name) } }; obj.greet(); // this指向全局对象(如window) ``` --- #### 3. **构造函数与原型** - **普通函数**:可作构造函数,通过`new`创建实例,拥有`prototype`属性。 ```javascript function Person(name) { this.name = name; } const alice = new Person("Alice"); ``` - **箭头函数**:**不能作为构造函数**,使用`new`会报错,且**无`prototype`属性**[^4]。 ```javascript const Person = (name) => { this.name = name; }; new Person("Alice"); // TypeError: Person is not a constructor ``` --- #### 4. **arguments对象** - **普通函数**:内部可通过`arguments`访问所有参数。 ```javascript function sum() { return Array.from(arguments).reduce((a, b) => a + b); } sum(1, 2, 3); // 6 ``` - **箭头函数**:**无`arguments`对象**,需用剩余参数(`...args`)替代[^4]。 ```javascript const sum = (...args) => args.reduce((a, b) => a + b); sum(1, 2, 3); // 6 ``` --- #### 5. **方法适用场景** - **箭头函数适用场景**: - 回调函数(如`setTimeout`、事件监听)[^4]。 - 需要固定`this`的场景(如Vue中组合式API的`setup`函数)。 ```javascript button.addEventListener("click", () => { console.log(this); // 继承外层this,避免误用event.target }); ``` - **普通函数适用场景**: - 需要动态`this`的方法(如对象方法)。 - 构造函数或需要`prototype`的场景。 --- ### 总结对比表 | **特性** | **箭头函数** | **普通函数** | |------------------|---------------------------|---------------------------| | `this`绑定 | 词法作用域(定义时确定) | 动态绑定(调用时确定) | | 构造函数 | ❌ 不可用 | ✅ 可用 | | `arguments`对象 | ❌ 无 | ✅ 有 | | 语法简洁性 | ✅ 更高 | ❌ 较低 | | 适用场景 | 回调、固定`this` | 对象方法、构造函数 | --- ### 相关问题 1. 如何在Vue的`methods`中选择箭头函数普通函数? 2. 箭头函数在`setTimeout`中如何处理`this`? 3. 为什么箭头函数不能用于对象方法?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值