1、箭头函数语法更加简洁、清晰
箭头函数的定义要比普通函数定义简洁、清晰得多,很快捷。
(1)、箭头函数体只有一个参数时,可以省略圆括号;
(2)、箭头函数没有function关键字;
(3)、箭头函数在函数体中只有return返回语句或者只有一句代码,return和{}可以省略。
2、箭头函数不会创建自己的this
箭头函数不会创建自己的this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this。
箭头函数没有自己的this
,它会捕获自己在定义时(注意,是定义时,不是调用时)所处的父作用域的this
,并继承这个this
值。所以,箭头函数中this
的指向在它被定义的时候就已经确定了,之后永远不会改变。
来看个例子:
function fun1() {
// setTimeout中使用普通函数
setTimeout(function () {
console.log(this);
}, 1000);
}
function fun2() {
// setTimeout中使用箭头函数
setTimeout(() => {
console.log(this);
}, 1000)
}
fun1()//Window
fun1.call({ obj: 123 });//Window
fun2()//Window
fun2.call({ obj: 123 });//{obj: 123}
上面这个例子,函数fun1
中的setTimeout
中使用普通函数,1秒后函数执行时,这时函数其实是在全局作用域执行的,所以this
指向Window
对象。
但是函数fun2
中的setTimeout
中使用的是箭头函数,这个箭头函数的this
在定义时就确定了,它继承了它外层fun2
的执行环境中的this
,而fun2
调用时this
被call
方法改变到了对象{id: 'Obj'}
中,所以输出'Obj'
。
.call()
/.apply()
/.bind()
方法可以用来动态修改函数执行时this
的指向,但由于箭头函数的this
定义时就已经确定且永远不会改变。所以使用这些方法永远也改变不了箭头函数this
的指向
let obj = {
a: 1,
b: function () {
console.log(this)//{a: 1, b: ƒ}
return () => {
console.log(this);
}
}
}
obj.b()()//{a: 1, b: ƒ}
// this的指向不会改变
obj.b().call({ obj: 123 }); // {a: 1, b: ƒ}
obj.b().apply({ obj: 123 }); // {a: 1, b: ƒ}
obj.b().bind({ obj: 123 })(); // {a: 1, b: ƒ}
4、箭头函数不能作为构造函数使用
我们先了解一下构造函数的new都做了些什么?简单来说,分为四步:
① JS内部首先会先生成一个对象;
② 再把函数中的this指向该对象;
③ 然后执行构造函数中的语句;
④ 最终返回该对象实例。
但是!!因为箭头函数没有自己的this
,它的this
其实是继承了父作用域中的this
,且this
指向永远不会随在哪里调用、被谁调用而改变,所以箭头函数不能作为构造函数使用,或者说构造函数不能定义成箭头函数,否则用new
调用时会报错!
let Fun = (name, age) => {
this.name = '张三';
this.age = 18;
};
let obj = new Fun('cao', 24);//报错:Fun is not a constructor
let sayHi = () => {
console.log('Hello World !')
};
console.log(sayHi.prototype); // undefined
箭头函数没有自己的arguments
对象。在箭头函数中访问arguments
实际上获得的是父作用域(函数)的值。
// 例子一
let fun = (val) => {
console.log(val); // 111
// 下面一行会报错
// Uncaught ReferenceError: arguments is not defined
// 因为外层全局环境没有arguments对象
console.log(arguments);
};
fun(111);
// 例子二
function outer(val1, val2) {
let argOut = arguments;
console.log(argOut); // ①
let fun = () => {
let argIn = arguments;
console.log(argIn); // ②
console.log(argOut === argIn); // ③
};
fun();
}
outer(111, 222);
上面例子二,①②③处的输出结果如下:
很明显,普通函数outer
内部的箭头函数fun
中的arguments
对象,其实是沿作用域链向上访问的外层outer
函数的arguments
对象。