1. 语法
按常规语法定义函数:
function funcName(params) { return params + 2; } funcName(2);
该函数改成箭头函数:
var funcName = params => params + 2; funcName(2);
我们来深入了解箭头函数的语法:
parameters => { statements; };
如果没有参数,那么可以进一步简化:
() => { statements; };
如果只有一个参数,可以省略括号:
parameters => { statements; };
如果函数体只有一句返回值,可以省略大括号和return
parameters => true;
等价于:
parameters => { return true;};
2. 箭头函数和普通函数的区别
(1) 没有this
箭头函数没有this,需要通过查找作用域链来确定this的值。因此如果箭头函数被非箭头函数包裹,this绑定的就是最近一层非箭头函数的this.
下面的例子是经常遇到的:
var obj = { birth: 1990, getAge: function () { var b = this.birth; // 1990 var fn = function () { console.log(this); // this指向的是window或者undefined return new Date().getFullYear() - this.birth; }; return fn(); } }; obj.getAge(); //NaN
上面的输出结果是NaN,因为fn是函数表达式,会有一个this指向它,不能拿到外层函数的this,而fn没有birth属性,所以this.birth是undefined,因此输出结果是NaN。
要修复这个问题,可以把外层的this保存起来,然后再内层函数使用:
var obj = { birth: 1990, getAge: function () { console.log(this.birth); var self = this; var fn = function () { return new Date().getFullYear() - self.birth; }; return fn(); } }; obj.getAge(); // 29
或者通过call或者apply将this传到内部函数中:
var obj = { birth: 1990, getAge: function () { var b = this.birth; // 1990 var fn = function () { return new Date().getFullYear() - this.birth; }; return fn.apply(this); // 或者:return fn.call(this); } }; obj.getAge(); // 29
现在可以通过箭头函数的方法解决了:
var obj = { birth: 1990, getAge: function () { var b = this.birth; // 1990 var fn = () => new Date().getFullYear() - this.birth; // this.birth仍是1990,因为this还是外部函数的this return fn(); } }; obj.getAge(); // 29
但是如果把外部函数也改成箭头函数,结果又是不一样的了:
var obj = { birth: 1990, getAge: (year) => { var b = this.birth; // 1990 var fn = () => { console.log(this); // window return new Date().getFullYear() - this.birth; // this.birth是undefined
} return fn(); } }; obj.getAge(); // NaN
因为外部函数也是箭头函数,所以不会有this, 就会按照作用域链继续往上寻找,这段代码的往上寻找,找到的this是window;
所以箭头函数this指向的关键是找到最近的非箭头函数的this
(2) 没有arguments
箭头函数没有自己的arguamnets对象, 但是箭头函数可以访问外围函数的arguments对象;看下面两个例子:
var Foo = () => {console.log(arguments)}; Foo(); // ReferenceError: arguments is not defined
function myFunc(age) { var Foo = () => {console.log(arguments)}; return Foo(); } myFunc(12);
代码执行结果:
第一段代码:输出箭头函数的argument报错,说明箭头函数是没有arguments对象的
第二段代码:在箭头函数中输出的arguments对象信息name为myFunc, 说明箭头函数中的是外围函数的arguments, 而第一段代码没有外围函数,所以会报错。
(3) 不能通过new关键字调用
js的函数有两个内部方法:[[call]]和[[Construct]]
当通过new调用构造函数时,执行[[Construct]]方法,创建一个实例对象,然后再执行函数体,将this绑定到实例上。当直接调用的时候,执行[[call]]方法,直接执行函数体。
箭头函数并没有[[Construct]]方法,不能被用作构造函数,因此通过new的方式调用,会报错。
var Fun = () => {}; var fun = new Fun(); // typeError: Fun is not a constructor
(4) 没有原型
由于不能使用new调用箭头函数,所以也没有构建原型的需求,于是箭头函数也不存在prototype这个属性。
var Fun = () => {}; console.log(Fun.prototype); // undefined
(5) 没有super
箭头函数没有原型,所以不能通过super来访问原型的属性,所以箭头函数是没有super的,super的值由最近一层非箭头函数决定。