这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
箭头函数
在ES6中新增了箭头函数,相对于传统函数来讲,箭头函数在写法上更加的简洁方便,
而且箭头函数在this方面也进行了改进,今天我们就来看看ES6中的箭头函数和箭头函数中的this
箭头函数的写法
再看箭头函数的写法之前,我们先看一下常规函数的写法,JS中的函数由function关键字,params参数和被花括号包裹的函数体所组成,为了区分我们先把这样的函数,叫做常规函数,常规函数既可以用声明式写法,也可以用赋值的写法:
声明式写法
function testA(a){
console.log(a)
}
testA('我是a')
赋值的写法
let testB = function(b){
console.log(b)
}
testB('我是B')
看完常规函数的写法后,我们一起来看看箭头函数的写法,定义箭头函数语法上要比常规函数简洁的多,ES6中允许使用箭头 => 来定义箭头函数,箭头函数省去了function关键字,函数的参数放在 => 前面的括号中,函数体跟在=>后面的花括号中,下面让我们来看看箭头函数的写法,
//常规函数
let testB = function(msg){
console.log(msg)
}
testB('我是常规函数')
// 箭头函数
let testB = (msg)=>{
console.log(msg)
}
testB('我是箭头函数')
这样对比看来箭头函数在写法上是不是比常规函数更改简洁和方便,不过箭头函数在写法还有一些规则,让我一起来看一下,我们从箭头函数的参数和函数体两个方面来看
箭头函数的参数
- 如果箭头函数没有参数,那么直接写一个空括号即可
let fun1 = () => { console.log('我是没有参数的'); };
- 如果箭头函数的参数只有一个,那么可以省去包裹参数的括号,如果有多个参数的话,就需要加括号了,并且每个参数用逗号分隔
//一个参数的
let fun1 = msg => { console.log(msg); };
fun2('我是有一个参数的')
// 多个参数的
let fun1 = (msg,msg1,msg2) => { console.log(msg,msg1,msg2); };
fun2('我是','有','多个参数的')
箭头函数的函数体
- 如果箭头函数的函数体只有一句代码,就是简单返回某个变量或者返回一个简单的JS表达式,可以省去函数体的大括号{ }和return,如果函数体没有{ }的话箭头函数会帮你return的,例如:
常规函数的写法:
// 返回变量
let fun = function(val){
return val
}
// 返回表达式
let sum = function(num1, num2) {
return num1 + num2;
};
箭头函数的写法:
//返回变量
let fun = val => val;
//返回表达式
let sum = (num1, num2) => num1 + num2;
- 如果箭头函数的函数体只有一句代码,就是返回一个对象,可以像下面这样写:
正确写法:
let item = id => ({ id: id, name: "Temp" });
错误写法:
let item = id => { id: id, name: "Temp" };
原因是因为对象的大括号会被箭头函数解析为函数体的大括号,所以会报错
- 如果箭头函数的函数体只有一条语句并且不需要返回值(最常见是调用一个函数),可以给这条语句前面加一个void关键字
let fun = () => void noRerurn();
箭头函数和常规函数的不同之处
我们看完上边箭头函数的写法可以看出,箭头函数在写法上比常规函数更加的简洁和清晰,相对来说箭头函数在写法上简洁和清晰,不太方便我们去读代码,接下来让我继续看一下箭头函数相对于常规函数还有那些不同
箭头函数没有原型属性(prototype)
// 箭头函数
let a = () => {}; console.log(a.prototype);
// undefined
// 普通函数
function a() {}; console.log(a.prototype);
// {constructor:f}。
箭头函数this指向不同
在常规函数中,this是指向调用它的对象。如果用作构造函数,this指向创建的对象实例。而箭头函数本身没有this,箭头函数的this指向是在定义时继承第一个外层函数的this,所以,箭头函数中的this指向在被定义的时候就已经确定,并且之后永远不会改变
注意:箭头函数中的this是在定义时就被指向的而不是在调用时 切记!!!
let obj = {
a: 10,
b: () => {
console.log(this.a); // undefined
console.log(this);
// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
},
c: function() {
console.log(this.a); // 10
console.log(this); // {a: 10, b: ƒ, c: ƒ}
}
}
obj.b();
obj.c();
call | apply | bind 无法改变箭头函数中this的指向
call | apply | bind方法可以用来修改函数执行时this的指向,但是箭头函数的this是在定义时就被指向了,而且是永远无法修改的,所以这些方法也无法修改箭头函数的this指向
let name = 'Kobe Bryant';
let fun = () => {
console.log(this.name)
};
fun(); // Toney
fun.call({ name: 'James' }); // Kobe Bryant
fun.apply({ name: 'Wade' }); // Kobe Bryant
fun.bind({ name: 'Jordan' })(); // Kobe Bryant
箭头函数不能作为构造函数使用
构造函数是通过new关键字来生成对象实例,生成对象实例的过程也是通过构造函数给实例绑定this的过程,而箭头函数没有自己的this。创建对象过程,new 首先会创建一个空对象,并将这个空对象的__proto__指向构造函数的prototype,从而继承原型上的方法,但是箭头函数没有prototype。因此不能使用箭头作为构造函数,也就不能通过new操作符来调用箭头函数
let People = (name, age) => {
this.name = name;
this.age = age;
};
let p = new People('Kobe Bryant', 41); //报错 People is not a constructor
箭头函数中没有arguments
argument是JavaScript中的一个关键字,用于指向调用者传入的所有参数。在箭头函数中如果要拿到传入的所有参数,需要用到rest参数(...变量名)
// 普通函数
function A(a){
console.log(arguments);
}
A(1,2,3,4,5,8); // [1, 2, 3, 4, 5, 8, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// 箭头函数
let B = (b)=>{
console.log(arguments);
}
B(2,92,32,32); // Uncaught ReferenceError: arguments is not defined
// rest参数...
let C = (...c) => {
console.log(c);
}
C(3,82,32,11323); // [3, 82, 32, 11323]
箭头函数不能当做Generator函数,不能使用yield关键字
箭头函数注意事项和适用以及不适用的场景
注意事项
- 箭头函数一条语句返回对象字面量,需要加括号
- 箭头函数在参数和箭头之间不能换行
- 箭头函数的解析顺序相对 || 靠前
- 箭头函数的this指向是在定义时,而不是调用时
- 如果外层的普通函数的this指向发生改变,箭头函数的this跟着会发生改变
适用场景
- 简单的函数表达式,得出唯一的 return 返回值,函数内部无 this 引用
- 内部函数需要借助bind调用外部函数的this时。
- 函数的参数操作需要用数组的方法时
不适用场景
- 执行语句比较多、需要用到递归、引用函数名以及事件绑定、解绑定。
- 箭头函数的this意外指向和代码的可读性
结语
关于ES6的箭头函数,我这里总结的还是不太全,如果有错误希望各位大佬多多指教,同时也希望这篇文章能帮助到一些同学学到一些东西,如果感觉写的还不错,能否给点个赞,也欢迎大家评论区讨论和探讨,谢谢大家