鸦杀's Blog

箭头函数

2018-08-31

注:以下内容是我在阅读了《深入理解es6》《es6标准入门》《你不知道的JavaScript(下)》后所汇总整理,如有雷同存属笔记。


es6中函数最大的改变大概就是添加了箭头函数吧,它设计的目标是用来替代IIFE。

箭头函数的写法有很多变种,基本上,可以按照以下规则来看:

  • 如果函数体只有一个return语句,可以省略{}return
  • 如果参数只有一个,可以省略()
  • 如果一个参数都没有,还是要在声明的时候写上()
  • 如果是一个空语句,直接这样写() => {}
  • 返回一个对象字面量为了与语句区分,需要在{}外面包一层():() => ({...})

箭头函数与传统的js函数的区别

  • 自身没有this、super、arguments和new.target绑定 。
    箭头函数中的this、super、arguments及new.target这些值由外围最近一层非箭头函数决定。因此也不能修改this。如果要获取箭头函数的参数,可用剩余参数。

可以在箭头函数上调用call、apply、bind方法,但箭头函数的this值不会受这些方法的影响。

1
2
3
4
5
6
7
8
(function() {
// this指向{ x: 'outer' }
return [
// 意图修改this指向为{ x: 'inner' },但是失败
(() => this.x).bind({ x: 'inner' })()
];
}).call({ x: 'outer' });
// ['outer']

  • 不能通过new关键字调用。
    箭头函数没有[[Construct]]方法,所以不能被用作构造函数,如果通过new调用,将报错。也正因为不能与new关键字混用,js引擎可以进一步优化它们的行为。

  • 没有原型prototype。
    由于不能通过new关键字调用箭头函数,因而没有构建原型的需求,箭头函数不存在prototype这个属性。它的设计初衷是“即用即弃”,不能用来定义新的类型。

  • 不支持重复的命名参数。
    无论在严格还是非严格模式,箭头函数都不支持重复的命名参数。而在传统函数的规定中,只有在严格模式下才不能有重复的命名参数。

  • yield关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作生成器。

箭头函数的使用场景

最常用的,是利用它的this指向特性
1、setTimeout,再也不用通过额外的that变量纠正this

1
2
3
4
5
6
7
8
9
10
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42

2、this指向”固定化”,这种特性很有利于封装回调函数。

1
2
3
4
5
6
7
8
9
10
11
12
var handler = {
id: '123456',

init: function() {
document.addEventListener('click',
event => this.doSomething(event.type), false);
},

doSomething: function(type) {
console.log('Handling ' + type + ' for ' + this.id);
}
};

箭头函数与变量解构结合使用

1
2
3
const full = ({ first, last }) => first + ' ' + last;
full({first: 'susan', last: 'li'})
// "susan li"

箭头函数与剩余参数结合

1
2
3
4
5
6
7
8
9
const numbers = (...nums) => nums;

numbers(1, 2, 3, 4, 5)
// [1,2,3,4,5]

const headAndTail = (head, ...tail) => [head, tail];

headAndTail(1, 2, 3, 4, 5)
// [1,[2,3,4,5]]

箭头函数与IIFE

箭头函数也支持IIFE:只不过它的括号只支持这种写法

1
2
3
4
5
6
7
var Fun = (() => {
return {
name: 'susan'
}
})()
Fun
// {name: "susan"}

小括号只包裹箭头函数定义。正常函数定义的IIFE即可以用小括号包裹函数体,也可以额外包裹函数调用部分。

箭头函数与高阶函数

高阶函数,就是返回函数的函数~如下例,fn就是一个高阶函数

1
2
let fn = a = b => c => b + c
fn(1)(2) //3

下面是一个部署管道机制(pipeline)的例子,即前一个函数的输出是后一个函数的输入。

1
2
3
4
5
6
7
8
9
const pipeline = (...funcs) =>
val => funcs.reduce((a, b) => b(a), val);

const plus1 = a => a + 1;
const mult2 = a => a * 2;
const addThenMult = pipeline(plus1, mult2);

addThenMult(5)
// 12

如何检测浏览器是否支持箭头函数

下面这种方式是不行的,因为如果不支持会直接报语法错误,根本不会执行到
ArrayFunctionEnabled = true这句

1
2
3
4
5
6
try {
var a = () => {}
ArrayFunctionEnabled = true
} catch(e) {
ArrayFunctionEnabled = false
}

需要通过Function构造器来实现,因为它是在运行时编译函数的,这样就把检测代码与编译隔绝开了。

1
2
3
4
5
6
try {
new Function('() => {}')
ArrayFunctionEnabled = true
} catch(e) {
ArrayFunctionEnabled = false
}

Tags: es6

扫描二维码,分享此文章