ES6中的箭头函数
1、基本语法:
使用ES6箭头函数语法定义函数,将原函数的“function”关键字和函数名都删掉,并使用“=>”连接参数列表和函数体。其中()里面的内容表示形参,{}表示函数体。
() => {}
const fn = () => {}
例如:
//箭头函数的写法
const fn =(x,y) =>{
console.log(x+y);
}
//等价于:
//匿名函数的写法
const fn = function(x,y){
console.log(x+y);
}
在这里我们令常量 fn 等于一个箭头函数,该函数有两个形参x和y,函数体是console.log(x+y)
。
简写方式:
(1)当函数参数只有一个,括号可以省略;但是没有参数时,括号不可以省略。
例如:
//只有一个参数
const fn =x =>{
console.log(x);
};
fn(2); // 2
//没有参数
const fun =() =>{
console.log('hello');
};
fun(); // 'hello'
(2)函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号
//箭头函数的写法
const fn =(x,y) => x+y
//等价于:
//匿名函数的写法
const fn = function(x,y){
return x+y;
}
如果是单表达式要返回自定义对象,要用x => ({key: x})
的方式。不写括号()会报错,因为和函数体的{ … }有语法冲突。
2、和匿名函数的区别
箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。
所以,箭头函数转成ES5的代码如下。
// ES6
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}
// ES5
function foo() {
var _this = this;
setTimeout(function () {
console.log('id:', _this.id);
}, 100);
}
上面代码中,转换后的ES5版本清楚地说明了,箭头函数里面根本没有自己的this,而是引用外层的this。
除了this,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:arguments、super、new.target。
另外,由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。
(function() {
return [
(() => this.x).bind({ x: 'inner' })()
];
}).call({ x: 'outer' });
// ['outer']
3、总结:箭头函数的特点
(1)箭头函数this为父作用域的this,不是调用时的this
例如:
const obj = { name: '张三'}
function fn () {
console.log(this); //指向obj
return () => {
console.log(this) //箭头函数的this就是函数体fn的this,指向obj
}
}
const resFn = fn.call(obj);
resFn();
一个经典面试题:
var obj={
age:20,
say:()=>{
alert(this.age); //undefined
}
}
obj.say();
分析:obj是一个对象,不能产生作用域。obj对象被定义在了全局作用域下,所以它的this指向的是window,所以say方法里面的this指向的也是window对象,由于windows对象中不含age属性,所以结果是undefined。
(2). 箭头函数不能作为构造函数,不能使用new
(3). 箭头函数没有arguments,caller,callee
(4). 箭头函数通过call和apply调用,不会改变this指向,只会传入参数
(5). 箭头函数没有原型属性
(6). 箭头函数不能作为Generator函数,不能使用yield关键字
(7). 箭头函数返回对象时,要加一个小括号
(8). 箭头函数在ES6 class中声明的方法为实例方法,不是原型方法
(9). 多重箭头函数就是一个高阶函数,相当于内嵌函数