一、箭头函数的介绍

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'});//Globalfn2.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();//OBJobj.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 allet aObj = {msg: 'a的this指向'};bObj = {msg: 'b的this指向'};a.call(aObj); //将a的this指向aObjb.call(bObj); //将b普通函数的this指向bObj 箭头函数内部的this指向也会指向bObjfunction 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)箭头函数不支持重复命名参数,普通函数可以重复命名参数

ES6中的箭头函数详细梳理相关推荐

  1. JS ES6中的箭头函数(Arrow Functions)使用

    转载这篇ES6的箭头函数方便自己查阅. ES6可以使用"箭头"(=>)定义函数,注意是函数,不要使用这种方式定义类(构造器). 一.语法 基础语法 (参数1, 参数2, -, ...

  2. 撤底理解es6中的箭头函数

    本质上 是一个函数,是function 是一个被编译层加工过的函数 用 babel 编译一下箭头函数看看,如下 //es6 const a = ()=>{ console.log(this) } ...

  3. ES6函数相关包含箭头函数

    转载地址:https://es6.ruanyifeng.com/?search=%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0&x=0&y=0#docs/fu ...

  4. Js 箭头函数 详细介绍(多种使用场景差异,你学会了吗?)

    简要认识 箭头函数是在ES6中添加的一种规范,简化了匿名函数定义的写法. 基本格式 完整写法 let fn = (x,y) => {return x + y; }//function()写法 l ...

  5. es6 中的箭头符号

    es6中的箭头符号"=>"用于函数的简写,具体例子如下: 情况一: var test0 = function(){return 1; } // 可以写成 var test0 ...

  6. php copy array,ES6中Array.copyWithin()函数用法的详解

    ES6为Array增加了copyWithin函数,用于操作当前数组自身,用来把某些个位置的元素复制并覆盖到其他位置上去.下面重点给大家介绍ES6中Array.copyWithin()函数的用法,需要的 ...

  7. 在React的render方法中使用箭头函数

    在 React 组件中绑定点击事件通常的做法使用 class 属性. class Foo extends Component {handleClick = () => {console.log( ...

  8. Vue相关面试问答TOP2(能不能在method中使⽤箭头函数、如何定义组件的data、v-if 和 v-show的区别、computed、watch、methods的区别、axios的特点....)

    1.能不能在method中使⽤箭头函数?               理论上可以使⽤,但是我不会使⽤,因为箭头函数中的this的指向与⼀般函数不同 ⼀般函数执⾏调⽤ 它的对象              ...

  9. Es6箭头函数详细用法

    箭头函数的声名方式: const ccc = (参数列表)=>{} 箭头函数的书写格式: 箭头函数的参数数量: 1.传入一个参数时,参数括号可以省略 举个例子: //放入一个参数(一个参数的时候 ...

  10. ES6特性:箭头函数转换,闭包

    箭头函数转换 箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象. // ES6写法 var handler = {id: "123456",init: fu ...

最新文章

  1. vue 网络请求 axios vue POST请求 vue GET请求 代码示例
  2. git如何查看缓存区文件内容_详解Git工作区、暂存区、历史记录区以及git reset、git revert、git checkout等撤销命令的区别...
  3. 谁是三国跳槽王:吕布成毫无规划的跳槽者
  4. 指针函数的一个范例,在单片机上运用它能让您的程序结构更明朗清晰,层次感强...
  5. VSFTP的PASSIVE模式的防火墙设置
  6. 远程删除用户照片?刚刚,拼多多承认了!
  7. getifaddrs
  8. CentOS 7 Hadoop安装配置
  9. 使用Eclipse,Kemulator模拟器配置J2ME工程
  10. 服务器主机防护系统有哪些,什么是DDoS防护主机?
  11. C# asp.net图片拼接方法
  12. 基于 Win32 的应用程序
  13. Android常见公有方法(隐藏虚拟按键/隐藏软键盘/获取屏幕宽高等)
  14. 关于偶的专业-信息工程
  15. 大数相乘 - 浮点数
  16. 《程序员的数学》第二册 (概率统计)
  17. 【算法】时间和空间复杂度
  18. 计算机网络课论文参考文献,热门计算机网络课程论文参考文献 计算机网络课程专著类参考文献哪里找...
  19. Cmap和Carray以及Cstring的使用以及MFC中的文件读写
  20. 怎样获取上传至腾讯开放平台app的下载链接

热门文章

  1. pytorch历史版本下载_Pytorch、Anaconda安装、Navidia版本更新
  2. 实时系统vxWorks - 配置多网口
  3. Unity 2D横版闯关游戏 (JUNGLE RULES)
  4. 基于Tushare量化分析示例
  5. pmf-automl源码分析
  6. 推荐系统的PMF - 概率矩阵分解和协同过滤
  7. 平均17.1K?2022软件测试员平均薪资出炉,看看你被平均了没~
  8. Python调用百度API进行动植物识别
  9. 计算机命令提示符开热点,将win7电脑变身wifi热点操作方法_电脑怎么开热点win7...
  10. CF 950C.Zebras 模拟,set