ES6中的箭头函数详细梳理

news2025/2/28 12:41:06

一、箭头函数的介绍

1.1 什么是箭头函数

ES6中允许使用=>来定义函数。箭头函数相当于匿名函数,并简化了函数定义。

1.2 基本语法

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

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

箭头函数在语法上比普通函数简洁多。箭头函数就是采用箭头=>来定义函数,省去关键字function。

函数的参数放在=>前面的括号中,函数体跟在=>后的花括号中

1.3 箭头函数的参数

①如果箭头函数没有参数,写空括号

//没有参数,写空括号
    let fn = () => {
        console.log('hello');
    };

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

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

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

    let fn = (val1, val2, val3, val4) => {
        return [val1, val2, val3, val4];
    }

1.4 箭头函数的函数体

①如果箭头函数的函数体只有一句执行代码,简单返回某个变量或者返回一个简单的js表达式,可以省去函数体花括号{ }

//返回某个简单变量val
let f = val => val;
// 等同于
let f = function (val) { return val };


//返回一个简单的js表达式num1+num2
let sum = (num1, num2) => num1 + num2;
// 等同于
let sum = function(num1, num2) {
  return num1 + num2;
};

②如果箭头函数的函数体只有一句代码,返回的不是变量和简单的js表达式,而是一个对象。

//错误写法—花括号会被解释为函数体
    let getItem = id => {
        id: id,
        name: 'gaby'
    };
//正确写法
    let getItem = id => ({
        id: id,
        name: 'gaby'
    });

③如果箭头函数的函数体只有一条语句且不需要返回值(最常用于回调函数),加上void关键字

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

箭头函数用于回调函数,常见简洁

//栗子1
//普通函数
    [1, 2, 3].map(function (x) {
        return x + x;
    });
//ES6箭头函数
[1, 2, 3].map(x => x + x);
//栗子2
//普通函数
    var result = [2, 4, 5, 1, 6].sort(function (a, b) {
        return a - b;
    });
//ES6箭头函数
	var result = [2, 4, 5, 1, 6].sort((a, b) => a - b);

二、箭头函数的this指向规则

2.1 箭头函数没有原型prototype,因此箭头函数没有this指向

    let fn = () => {
        console.log('Hello World !')
    };
    console.log(fn.prototype); // undefined

在这里插入图片描述

2.2 箭头函数不会创建自己的this,如果存在外层第一个普通函数,在定义的时候会继承它的this

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

(1)栗子1
    var id = 'Global';
    //普通函数
    function fn1() {
        setTimeout(function () {
            console.log(this.id)

        }, 1000);
    }
    //箭头函数
    function fn2() {
        setTimeout(() => {
            console.log(this.id)
        }, 1000);
    }

    fn1.call({
        id: 'obj'
    });//Global

    fn2.call({
        id: 'obj'
    });//obj

在这里插入图片描述

解析:普通函数的setTimeout 一秒后执行是在全局作用域,所有this指向window对象,this.id指向了全局变量id,输出Golbal。箭头函数的this在定义的时候就确定了,继承fn2的执行环境中的this,fn2的this指向被call方法改变绑定到obj这个对象

(2)栗子2
    var id = 'Global';
    var obj = {
        id: 'OBJ',
        a: function () {
            console.log(this.id)
        },//方法a普通函数定义
        b: () => {
            console.log(this.id)
        }//方法b用箭头函数定义
    };
    obj.a();//OBJ
    obj.b();//Global

在这里插入图片描述

解析:普通函数作为对象的方法调用,this指向所属的对象(谁调用它就指向谁),this.id 就是obj.id;箭头函数继承定义它的执行环境的this,指向window对象,指向全局变量,输出Global。花括号{}无法形成一个单独的执行环境,所有它依然在全局中。

2.3 箭头函数的this是继承而来的永远不会变,call/apply/bind也无法改变

.call()/.apply()/.bind()方法可以用来动态修改函数执行时this的指向,但由于箭头函数的this定义时就已经确定且永远不会改变

    var name = 'gaby'
    var person = {
        name: 'gabrielle',
        say: function () {
            console.log('say hello', this.name)
        }, //普通函数
        say2: () => {
            console.log('say2 hello', this.name)
        } //箭头函数
    }
    person.say.call({
        name: 'Mike'
    })
    person.say2.call({
        name: 'Amy'
    })

在这里插入图片描述

解析:say的普通函数通过call调用已经改变this指向。say2箭头函数调用call绑定尝试改变this指向,但是仍然打印出外一层普通函数的this指向,window对象的全局变量name。

2.4 箭头函数this指向只能间接修改

间接修改:修改被继承的普通函数的this指向,箭头函数的this指向也会跟着改变。

箭头函数的this指向定义时所在的外层第一个普通函数,跟使用的位置没有关系。

    let al
    let aObj = {
        msg: 'a的this指向'
    };
    bObj = {
        msg: 'b的this指向'
    };
    a.call(aObj); //将a的this指向aObj
    b.call(bObj); //将b普通函数的this指向bObj 箭头函数内部的this指向也会指向bObj

    function b() {
        al();
    }

    function a() {
        al = () => {
            console.log(this, 'this指向定义时外层第一个普通函数 ')
        };
    }

在这里插入图片描述

2.5 箭头函数外层没有函数,严格模式和非严格模式下它的this都会指向window全局对象

箭头函数的this指向继承自外层第一个普通函数的this,那么如果没有外层函数,它的this指向哪里?

this的绑定规则:非严格模式下,默认绑定的this指向全局对象,严格模式下this指向undefined。

如果箭头函数外层没有普通函数继承,箭头函数在全局作用域下,严格模式和非严格模式下它的this都会指向window(全局对象)

2.6 多层嵌套函数this指向

箭头函数中的this引用的是最近作用域中的this,是向外层作用域中,一层层查找this,直到有this的定义。

2.7 箭头函数不能作为构造函数使用new

构造函数做了什么?

①JS内部首先会先生成一个对象

②再把函数中的this指向该对象

③然后执行构造函数中的语句

④最终返回该对象实例

箭头函数没有自己的this,this继承外层执行环境中的this,且this永远不会改变。new会报错

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

    let person = new fn('gaby', 20)

在这里插入图片描述

2.8 箭头函数不支持new.target

ES6新引入的属性,普通函数可以通过new调用,new.target返回该函数的引用。用于确定构造函数是否为new调用。箭头函数并不能作为构造函数使用new,自然也不支持new.targer。

(1)箭头函数的this指向全局对象,在箭头函数中使用箭头函数会报错
    let fn = () => {
        console.log(new.target)
    };
    fn()

在这里插入图片描述

(2)箭头函数的this指向普通函数,它的new.target就是指向该普通函数的引用
    new fn2();

    function fn2() {
        let fn = () => {
            console.log(new.target)
        };
        fn();
    }

在这里插入图片描述

三、箭头函数的arguments规则

3.1 箭头函数没有自己的arguments

(1)箭头函数处于全局作用域中

箭头函数的this指向全局对象,会报arguments未声明的错。

    let fn = name => {
        console.log(arguments)
    }
    let fn2 = function (name) {
        console.log(arguments)
    }
    //fn()
    fn2()

在这里插入图片描述

    let fn = name => {
        console.log(arguments)
    }
    let fn2 = function (name) {
        console.log(arguments)
    }
    fn()
    fn2()

在这里插入图片描述

解析:普通函数可以打印arguments,箭头函数报错。因为箭头函数处于全局作用域中,在全局作用域没有arguments的定义,箭头函数本身没有arguments,所以报错。

(2)箭头函数的this如果指向普通函数,它的argumens继承于该普通函数
    let fn2 = function (name) {
        console.log('fn2:', arguments)
        let fn = name => {
            console.log('fn:', arguments)
        }
        fn()
    }
    fn2('gaby')

在这里插入图片描述

解析:两个函数打印的argument相同,都是fn2函数的arguments。

总结

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

3.2 可以用rest替代,rest参数获取函数的多余参数

rest是ES6的API,用于获取函数不定数量的参数数组。这个API可以用来替代arguments。

(1)基本用法
    //形式是...变量名 
	let fn = (first, ...arr) => {
        console.log(first, arr);
    }
    fn(1, 2, 3, 4);

在这里插入图片描述

解析:rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。获取函数的第一个确定的参数,以及用一个变量接收其他剩余函数的实例。

(2)使用注意事项

①rest必须是函数的最后一位参数

    let a = (first, ...rest, three) => {
        console.log(first, rest, three);
    };
    a(1, 2, 3, 4);

在这里插入图片描述

②函数的length属性不包括rest

(3)rest和arguments函数比较

①箭头函数和普通函数都可以使用rest参数,而arguments只能普通函数用。

②接收参数rest比arguments更加灵活,完全可以自定义。

③rest是一个真正的数组可以使用数组API,arguments只是一个类数组。

3.3 箭头函数不支持重复函数参数的名称

    function fn(name, name) {
        console.log('fn2:', name)
    }
    let fn2 = (name, name) => {
        console.log('fn:', name)
    }
    fn('wang', 'gaby')
    fn2('wang', 'gaby')

在这里插入图片描述

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

四、箭头函数的注意事项

①函数箭头一条语句返回对象字面量,需要加括号。

②箭头函数在参数和箭头之间不能换行

③箭头函数的解析顺序相对||靠前

五、箭头函数不适用场景

(1)对象方法,且方法使用了this

对象无法构造单独的作用域

    var name = 'gaby'
    var person = {
        name: 'gabrielle',
        say: function () {
            console.log('say hello', this.name)
        }, //普通函数
        say2: () => {
            console.log('say2 hello', this.name)
        } //箭头函数
    }
    person.say()
    person.say2()

在这里插入图片描述

解析:person.say2()方法是一个箭头函数,调用person.say2()的时候this指向全局对象,达不到预期。对象无法构成单独的作用域,定义say2()箭头函数的时候作用域在全局作用域。

(2)回调函数的动态this
    var button = document.querySelector('.btn');
    button.addEventListener('click', () => {
        this.classList.toggle('on');
    });

在这里插入图片描述

解析:报错。按钮点击是一个回调函数,而箭头函数内部的this指向外一层普通函数的this,在这里就是window,所以报错。改成普通函数就不会报错

六、箭头函数与普通函数简单区别总结

(1)箭头函数语法更简洁清晰,快捷。

(2)箭头函数没有原型prototype,并不会自己创建this,并且this不能被修改,call等都不能修改到。只能间接修改被继承的this

(3)箭头函数的this在定义时就定了,继承外一层的普通函数

(4)如果箭头函数外一层再外一层都不能找到普通函数,在严格和非严格情况下都会指向window对象

(5)箭头函数的this指向全局,使用arguments会报未声明的错误

(6)箭头函数的this指向外一层的普通函数,使用argument继承该普通函数

(7)箭头函数不能构造函数,不能new.target,不能new,没有constructor

(8)箭头函数不支持重复命名参数,普通函数可以重复命名参数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/405041.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue是什么?vue的优点有哪些?

目录 一、vue是什么 二、为什么要用Vue? 1. 组件化 2. MVVM 数据双向绑定 3. 响应式 虚拟DOM 4.生命周期 三、Vue的优点 1. 轻量级 2. 高性能 3. 好上手 4. 插件化 5. 便于测试 6.运行速度更快 7.视图,数据,结构分离 一、vue是什么 Vue是一套用于构建…

vue基础用法基础原理整理

vue基础用法&基础原理整理 md文件地址:https://gitee.com/gaohan888/note 1. vue基础知识和原理 1.1 初识Vue 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象demo容器里的代码依然符合html规范,只不过混入了一些特…

Vue3 中路由Vue Router 的使用

目录前言:一、什么是 Vue Router ?二、路由的使用1、路由的安装2、路由的模式3、创建路由模块4、声明路由链接和占位符三、路由的重定向和别名四、嵌套路由五、声明式和编程式导航1、声明式导航2、编程式导航3、替换当前位置4、路由历史总结:…

如何使用vue-cli来搭建vue项目?详细步骤跟着我来吧!

目录 一、什么是vue-cli? 二、前提:搭建好NodeJS环境 安装vue-cli 三、使用脚手架vue-cli(2.X版)来构建项目 第一步 第二步 第三步 第三步 第四步 三、SPA完成路由的开发 第一步 ​编辑第二步 第三步 第四步 第四步 四、嵌套路由 使用children属性 五、知…

SpringMVC的文件上传

6.SpringMVC的文件上传 6.1-SpringMVC的请求-文件上传-客户端表单实现(应用) 文件上传客户端表单需要满足&#xff1a; 表单项type“file” 表单的提交方式是post 表单的enctype属性是多部分表单形式&#xff0c;及enctype“multipart/form-data” <form action"…

怎样创建一个VUE项目(超简单)

目录 一、安装node.js 二、搭建vue环境 1、全局安装vue/cli模块包 2、执行命令 3、检查是否安装成功 三、创建vue项目 1、创建项目 2、选择模板和包管理器&#xff0c;等待项目创建完毕 四、启动vue项目 1、执行命令 2、浏览项目页面 五、vue项目目录文件含义和作用…

2022 uniapp基础掌握及面试题整理

1.uniapp优缺点 优点: a. 一套代码可以生成多端 b. 学习成本低,语法是vue的,组件是小程序的 c. 拓展能力强 d. 使用HBuilderX开发,支持vue语法 e. 突破了系统对H5调用原生能力的限制 缺点: a. 问世时间短,很多地方不完善 b. 社区不大 c. …

2022前端面试题汇总(持续更新中~)

目录 1. 防抖和节流 2. js闭包 vue中的data为什么是一个函数&#xff1f;&#xff08;面试常问&#xff09; 3. ES6面试题 3.1 var let const 区别 3.2 解构 3.3 如何利用es6快速的去重&#xff1f; 3.4 Promise 面试题 以下代码的执行结果是&#xff1f; 4. Vue相关…

前端面试八股文(超详细)

JavaScript \1. Promise 的理解 Promise 是一种为了避免回调地狱的异步解决方案 2. Promise 是一种状态机&#xff1a; pending&#xff08;进行中&#xff09;、fulfilled&#xff08;已成功&#xff09;和rejected&#xff08;已失败&#xff09; 只有异步操作的结果&#…

2022最全最新前端面试题(附加解答)

JS 1、说一下innerHTML 与 innerText的作用与区别&#xff1f; 作用&#xff1a;都可以获取或者设置元素的内容区别&#xff1a;innerHTML可以解析内容中的html标签innerText不能解析内容中的html标签 2、JavaScript 由以下三部分组成&#xff1a; ECMAScript&#xff08;语…

Java Web 项目入门指南(http、Servlet、Request、Response、ServletContext、会话技术[cookie、session]、Filter、Listener)

概述 web 服务器、项目、资源概述 web 服务器&#xff1a;可以被浏览器访问到的服务器 常见的 web 服务器&#xff1a; tomcat&#xff1a;中小型的服务器软件&#xff0c;免费开源&#xff0c;支持 JSP 和 Servlet apache 公司的产品WebLogic&#xff1a;Oracle 公司的产品…

Vue.js 状态管理:Pinia 与 Vuex

&#x1f482; 个人网站:【海拥】【摸鱼游戏】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录Pinia 和 Vuex 简…

vue3 一个基于pinia简单易懂的系统权限管理实现方案,vue-router动态路由异步问题解决

文章目录前情提要应用场景实战解析1、控制添加路由2、实践观察3、控制功能4、解决异步路由问题最后前情提要 作为项目经验稀少的vue开发者来说&#xff0c;在关键技术点上的经验不多&#xff0c;我希望通过我的思想和实践&#xff0c;把好的东西分享在这里&#xff0c;目的是进…

【前端进阶】-TypeScript类型声明文件详解及使用说明

前言 博主主页&#x1f449;&#x1f3fb;蜡笔雏田学代码 专栏链接&#x1f449;&#x1f3fb;【TypeScript专栏】 前三篇文章讲解了TypeScript的一些高级类型 详细内容请阅读如下&#xff1a;&#x1f53d; 【前端进阶】-TypeScript高级类型 | 泛型约束、泛型接口、泛型工具类…

【live2D看板娘】为你的网站添加萌萌的二次元板娘,这都拿不下你?

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

渐进式 Web 应用程序介绍

&#x1f482; 个人网站:【海拥】【摸鱼游戏】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 构建 PWA 背后的核心思…

【Promise】一文带你了解promise并解决回调地狱

文章目录Promise为什么需要promise需求回调地狱Promise的基本使用promise实例promise的状态promise状态的改变promise的结果promise方法then方法通过then方法获取promise的结果then方法的返回值catch方法解决回调地狱Promise 为什么需要promise 需求 通过ajax请求id,再根据id…

2022 最新 Vue 3.0 面试题

2022 最新 Vue 3.0 面试题1、Vue 的最大的优势是什么&#xff1f;&#xff08;必会&#xff09;2、Vue 和 jQuery 两者之间的区别是什么&#xff1f;&#xff08;必会&#xff09;3、MVVM 和 MVC 区别是什么&#xff1f;哪些场景适合&#xff1f;&#xff08;必会&#xff09;4…

如何快速获取网页源码(直接把网站的 js css html 扒下来的)

如何快速获取网页源码&#xff1f; 我们在学习和研究的时候,或者看到非常酷炫的页面效果&#xff0c;需要网站的源代码进行借鉴&#xff0c;但每次需要下载网站源代码&#xff0c;我们都需要找到一个&#xff0c;下载一个&#xff0c;每次只能下载一个文件&#xff0c;非常缓慢…

vue-quill-editor富文本编辑器-扩展表格、图片调整大小

上篇文章已经讲到、vue-quill-editor的基本配置和图片转成url 这篇文章主要使用插件来完成 图片调整大小 和 表格的插件使用&#xff08;这两个目前quill 版本并不兼容 如果有大神解决了还望指点&#xff09; 参考文章&#xff1a; vue-quill-editor 富文本编辑器支持图片拖拽…