0x000 概述
箭头函数有两个作用:
- 更简短的写法
- 不绑定
this
0x001 语法一表览
()=>{}
()=>{console.log('arrow');return null}
()=>'hello'
(num1, num2)=>num1+num2
num=>++num
()=>({name:'arrow'})
0x002 写法
-
正规一点
let add = (num1, num2)=>{ return num1 + num2 } add(1, 2)
声明了一个
add
变量,该变量是一个加法函数,该函数有两个形参:num1
、num2
,返回值为这两个参数相加的结果 -
单参数
let increment = num=>{ return num + 1 }
上面声明了一个
increment
变量,该变量是一个自增函数,该参数只有一个形参num
,返回值为该参数自增1
,因为只有一个参数,所以可以省略箭头函数参数列表的()
-
无参数
let now = () => { return Date.now() } let now==>{} // Uncaught SyntaxError: Unexpected token ==
上面声明了一个
now
变量,该变量是一个函数,可以获取当前时间戳,因为不需要参数,所以参数列表置空,但是这种情况下不能将()
省略,否则将导致语法错误 -
单一返回值
let now = () => Date.now()
上面函数还可以简写为以下方式,因为函数体只有一句话,所以可以省略
{}
和return
-
单一返回值:返回对象字面量
虽然箭头函数可以省略{}
和return
,但是在返回一个对象字面量的时候要格外注意,如果是像下面的写法,虽然在语法检查的时候不会报错,但是和你所期望的可能不太一样,比如这里,你希望得到的数据是{name:'hello'}
,但是结果却是undefined
。let data=()=>{name:'hello'} // 不会报错 console.log(data()) // undefined
为什么呢?用
babel
解析一下可以发现,被解析成了
var data = function data() { name: 'hello'; };
并没有
return
,对比4
的例子
所以,其实{name:'hello'}
被解析成了函数体,{}
是函数的{}
,而不是对象的{}
,而name:'hello'
被解析成了语句,这种语句不常用,却是满足js
语法的,叫做标签,案例:var str = ""; loop1: for (var i = 0; i < 5; i++) { if (i === 1) { continue loop1; } str = str + i; } console.log(str); // 0234
所以如果箭头函数需要返回单一的对象字面量,需要加对
()
let data=()=>({name:'hello'})
0x003 不绑定this
看下面一种情况
function Person() {
this.age = 0;
setInterval(function growUp() {
console.log(this.age)
}, 1000);
}
var p = new Person();
通常,我们希望在setInterval
的回调函数中访问Person
的变量,比如age
,但是每个新定义的函数都有自己的this
,所以这里的this
是growUp
的this
,并不是Person
的this
,这将导致this.age
将会得到undefined
,为了解决这种问题,我们通常会使用折中的解决方案:
function Person() {
this.age = 0;
var that=this
setInterval(function growUp() {
console.log(that.age)
}, 1000);
}
var p = new Person();
用一个临时变量that
来持有this
,避免使用growUp
的this
,这个时候就轮到箭头函数上场了:
function Person() {
this.age = 0;
setInterval(()=> {
console.log(this.age)
}, 1000);
}
var p = new Person();
在箭头函数中,是不会绑定this
的,也就是他没有自己的this
,所以这个时候,他的this
,就是Person
的this
。这就是所谓的箭头函数不绑定this
,而在我看来,回调函数就是箭头函数最好的归宿。babel
解析之后的结果其实还是老方法:
"use strict";
function Person() {
var _this = this;
this.age = 0;
setInterval(function () {
console.log(_this.age);
}, 1000);
}
var p = new Person();
0x004 注意
-
箭头函数支持默认参数
let add = (num1 = 0, num2) => num1 + num2
-
箭头函数支持剩余参数
let add = (...numList) => numList.reduce((n1, n2) => n1 + n2)
-
箭头函数支持参数列表解构
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
-
箭头函数不支持
arguments
,如果要使用arguments
,推荐上面的剩余参数的写法// 栗子1 var arguments = [1, 2, 3]; var arr = () => arguments[0]; arr(); // 1 // 栗子2 function foo(n) { var f = () => arguments[0] + n; // 隐式绑定 foo 函数的 arguments 对象. arguments[0] 是 n return f(); } foo(1); // 2 // 栗子3 function foo() { var f = (...args) => args[0]; return f(2); } foo(1); // 2
-
Object.defineProperty()
会出现意料之外的影响'use strict'; var obj = { a: 10 }; Object.defineProperty(obj, "b", { get: () => { console.log(this.a, typeof this.a, this); return this.a+10; // 代表全局对象 'Window', 因此 'this.a' 返回 'undefined' } });
-
无法和
new
一起使用var Foo = () => {}; var foo = new Foo(); // TypeError: Foo is not a constructor
-
没有
prototype
var Foo = () => {}; console.log(Foo.prototype); // undefined
-
解析顺序有影响
let callback; callback = callback || function() {}; // ok callback = callback || () => {}; // SyntaxError: invalid arrow-function arguments callback = callback || (() => {}); // ok
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。