箭头函数
var f = v => v;
//等同于
var f = function () {
return v
}
-
多个参数或不需要参数
var f = () => 5;
//等同于
var f = function () { return 5 }var sum = (num1, num2) => num1 + num2;
//等同于
var f = function (num1, num2) {
return num1 + num2
} -
如果箭头函数的代码块部分多于一条语句,就要使用大括号将他们括起来,并且使用return语句返回。由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。
//报错
let getItem = id => {id: id, name: ‘temp’};//不报错
let getItem = id => ({id: id, name: ‘temp’});
下面是一种特殊情况,虽然可以运行,但会得到错误的结果。
let foo = () => { a: 1 };
foo() // undefined
上面代码中,原始意图是返回一个对象{ a: 1 },但是由于引擎认为大括号是代码块,所以执行了一行语句a: 1。这时,a可以被解释为语句的标签,因此实际执行的语句是1;,然后函数就结束了,没有返回值。
如果箭头函数只有一行语句,且不需要返回值,可以采用下面的写法,就不用写大括号了。
let fn = () => void doesNotReturn();
注意
-
函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
this对象的指向是可变的,但是在箭头函数中,它是固定的
function foo () { setTimeout(()=>{ console.log('id:', this.id); }, 100); } var id = 21; foo.call({id: 42}); // id:42
箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。
function Timer () { this.s1 = 0; this.s2 = 0; // 箭头函数 setInterval(() => this.s1++, 1000); //普通函数 setInterval(function () { this.s2++; }, 1000); } var timer = new Timer(); setTimeout(() => console.log('s1: ', timer.s1), 3100); setTimeout(() => console.log('s2: ', timer.s2), 3100); // s1: 3 // s2: 0
Timer函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的this绑定定义时所在的作用域(即Timer函数),后者的this只想运行时所在的作用域(即全局对象)。所以,3100毫秒之后,timer.s1被更新了3次,而timer.s2一次都没更新。
箭头函数可以让this指向固定化,这种特性很有利于封装回调函数。
var handle = { id: '123456', init: function () { document.addEventListener('click', event => this.doSomething(event.type), false); }, doSomething: function (type) { console.log('Handling ' + type + ' for ' + this.id) } }
上面代码的init方法中,使用了箭头函数,这导致这个箭头函数里面的this,总是指向handle对象。否则,回调函数运行时,this.doSomething这一行会报错,因为此时this指向document对象。
this指向的固定化(箭头函数使得this从“动态”变成“静态”),并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this指向,所以也就不能用作构造函数。
除了this,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:arguments、super、new.target
另外,由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。
-
不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
-
不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。
-
不可以使用yield命令,因此箭头函数不能用作Generator函数。
什么是this
函数实际上是对象。每个函数都是Function类型的实例,而且都有与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定(函数是对象,函数名是指针)。
函数声明会在解析过程中得到提升,函数表达式则不会。
每个函数在被调用时都会自动取得两个特殊变量:this和arguments。
arguments.callee
this引用的是函数据以执行的环境对象——或者也可以说是this值。在调用函数之前,this的值并不确定,因此this可能会在代码执行过程中引用不同的对象。
call() apply()能够扩充函数赖以运行的作用域。(P117)