箭头函数详解

逻辑追月人
• 阅读 671

定义箭头函数

ES6允许使用箭头 => 定义函数

let v = 100

// 箭头函数
let f = a => v;

// 等同于
let f2 = function (a){
 return v
}

// 等同于
let f3 = (a) => { return v }

console.log(f());  // 100
console.log(f2()); // 100
console.log(f3()); // 100


箭头函数参数

箭头函数中,使用圆括号()代表参数的部分

// 无参数
let a1 = () => 5;

// 等同于
let a2 = function () {return 5}
// 有参数
let a3 = (num1,num2) => num1 + num2

// 等同于
let a4 = function (num1,num2) { return num1 + num2}

如果箭头函数中的代码块为一句话,可以省略大括号。
如果箭头函数中的代码块多于一句,需要使用大括号括起来,使用return可以返回数据。


大括号被解释为代码块,如果箭头函数返回的是一个对象,就必须在对象外面加上括号,否则报错

// 错误写法
let b1 = id => { id : id , name : '东方不败'}  // 报错
// 正确写法
let id = 1
let b2 = id => ({id,name:'东方不败'})
console.log(b2()); // id : undefined ,name :'东方不败'

上面这个代码块中,箭头函数参数为id,调用b2函数时未传参数,所以idundefined,参数部分其实是定义了一个let id;id并没有赋值,所以是undefined


在普通函数中,函数没有参数且函数内部没有定义变量,内部的变量会向上寻找变量,所以这里内部returnid指向的是外层全局变量id

let id = 1
function b3(){
    return {id,name:'东方求败'}
    } 
console.log(b3());  // id : 1 ,name :'东方不败'

如果函数有参数,但是调用函数时未传参,那么该参数就是undefined

// 这里有一个参数,但是调用的时候没有传参,所以id为undefined
function b4(id){
    return {id,name:'东方求败'}
 }
console.log(b4());  // id : undefined ,name :'东方不败'


函数参数部分其实是有一个作用域的,参数部分的id其实是定义了一个let id,下面这个例子就能说明:

// 报错
let id = 1
function b5(id = id){
    return {id,name:'东方求败'}
}
b5()

这里的id其实就是let id = id ,id为一个未声明的变量,赋值id = id,报错

// 调用函数不携带参数获取外层全局变量的正确方法
let id = 1
function b5(val = id){
    return {val,name:'东方求败'}
  }
console.log(b5());  // id : 1 ,name :'东方不败'


箭头函数返回值

如果箭头函数只有一句话且没有返回值,可以在内容前面加void,不需要写大括号,直接写内容即可

let fooEmpty = () => void '无返回值';
console.log('无:',fooEmpty());   // 无: undefined

箭头函数有返回值

let fooHave = () => '有返回值';
console.log('有:',fooHave());  // 有: 有返回值


箭头函数大括号

let foo = () => {a : 1}
console.log(foo());  // undefined

上面例子是一种特殊情况,虽然可以运行,但的到的结果是错误的,因为大括号在箭头函数中被认为是代码块,这里的箭头函数并不是return了一个{a:1}的对象,而是执行了一个表达式 a : 1,表达式执行完成后结束运行,没有返回值。
正常的写法如下:

let foo2 = () => { return {a : 1} }
console.log(foo2());  // {a : 1}


箭头函数解构赋值

在参数部分传入对象,解构赋值

let foo3val = {id:1, name:'孙悟空'}
let foo3 = ({id,name}) => console.log(`id:${id},名称:${name}`);
foo3(foo3val)  // id:1,名称:孙悟空

有了解构赋值后,箭头函数可以使表达更简洁、更加直观,例如这里封装一个简单的工具函数,一行代码完成求奇偶的工具函数封装

const isEven = n => n % 2 === 0

console.log(isEven(2));  // true
console.log(isEven(3));  // false


简化回调函数

普通函数写法

let fil = [1,2,3].filter(function(x){
   return x == 2
})
console.log(fil); // [2]

箭头函数写法,一行搞定

let fil2 = [1,2,3].filter(el=> el == 2 )
console.log(fil2); // [2]


箭头函数的注意点

1、箭头函数没有this对象
2、不可以当做构造函数,也就是说,不可以对箭头函数使用new命令,否则报错
3、不能使用arguments对象,该对象在函数体内不存在
4、不能使用yield命令,因为箭头函数不能用作Generator函数

箭头函数导致this总是指向函数定义生效时所在的对象


箭头函数this指向

在箭头函数的使用注意点中,最需要注意的就是this指向问题,这里举一个例子说明箭头函数this指向的问题

function arrows(){

    console.log('name:',this.name);     // 中国工艺美术史
    
    setTimeout(()=>{
       console.log('name:', this.name);  // 中国工艺美术史
    },100)

    setTimeout(function(){
        console.log('name:', this.name); // 艺术概论
    },100)
 }
    
   var name = '艺术概论'
   arrows.call({name : '中国工艺美术史'})  // name: 中国工艺美术史
call函数:
第一个参数表示:想让this指向的对象(obj)
第二个参数表示:传进去的实参
如果call的第一个参数未传值,或者传值为null,那么arrowsthis指向为window
这里传入第一个传参数,this指向obj对象

第一个定时器setTimeout使用了箭头函数,在普通函数中,setTimeout指向的是window,但这里setTimeout使用了箭头函数,导致定时器指向的是调用函数定义生效时所在的对象,所以这里打印的是 中国工艺美术史,而不是最外层全局变量 艺术概论
第二个定时器setTimeout没有使用箭头函数,即使使用call()方法,在函数内部的定时器还是指向window

箭头函数没有自己的this,导致内部的this就是外层代码块的this。正是因为没有this,所以也就不能用作构造函数。

箭头函数里没有自己的this,而是引用外层的this。下面是 Babel 转箭头函数产生的 ES5 代码,就能清楚地说明this的指向。

// ES6
function foo() {
    setTimeout(() => {
        console.log('id:', this.id);
    }, 100);
}

// ES5
function foo() {
    var _this = this;
    
    setTimeout(function () {
        console.log('id:', _this.id);
    }, 100);
} 


箭头函数不适用的场合

1:对象内定义箭头函数

let cat = {
    level : 9,
    jumps : ()=> {
      this.level
    }
}

在这个例子中,cat.jumps()是一个箭头函数,这是错误的。如果cat.jumps()是一个普通函数, 该方法内部的this指向cat。如果调用cat.jumps()是一个箭头函数时,this指向全局对象。因为对象不构成单独的作用域,导致jumps箭头函数定义时的作用域是全局作用域。

2:需要动态this的时候,不应该使用箭头函数

let button = document.getElementById('news')

button.addEventListener('click',()=>{
    this.classList.toggle('on')
})

上面代码运行时,点击按钮报错,因为button监听函数是一个箭头函数,导致内部的this是全局对象。如果改成普通函数,this就会动态指向被点击的按钮对象。

另外,如果函数体很复杂,有许多行,或者函数内部有大量的读写操作,不单纯是为了计算值,这时也不应该使用箭头函数,而是要使用普通函数,这样可以提高代码可读性。


案例源码:https://gitee.com/wang_fan_w/es6-science-institute

如果觉得这篇文章对你有帮助,欢迎点亮一下star哟

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
3年前
SQL利用函数或存储过程求男或女的总分平均分
!(https://oscimg.oschina.net/oscnet/633e11621f3e13e713cf063db00d72c8aa0.png)函数alterfunctionxb(@xingbievarchar(2))returnstableas
Stella981 Stella981
3年前
AndroidStudio封装SDK的那些事
<divclass"markdown\_views"<!flowchart箭头图标勿删<svgxmlns"http://www.w3.org/2000/svg"style"display:none;"<pathstrokelinecap"round"d"M5,00,2.55,5z"id"raphael
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这