箭头函数的学习参考了以下几位大大们的博客~仅为自己的学习笔记。
http://es6.ruanyifeng.com/#docs/function
https://www.liaoxuefeng.com/wiki/1022910821149312/1031549578462080
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions
https://www.jianshu.com/p/a416cb02e4a2
1. 什么是箭头函数
ES6允许使用箭头(=>)定义函数。如
var f = v => v;
这个箭头函数相当于
var f = function(v){
return v;
}
我们可以这么理解,**箭头的左侧为函数的参数体,箭头右侧为函数的执行体。**一个箭头函数相当于一个匿名函数,如
(v => console.log(v))(2) //2
相当于
(function(v){
console.log(v)
})(2)
1.1 参数何时加()
上面的例子是箭头函数的参数为一个时的写法。
(1)箭头函数无参数时,箭头的左侧应该由一个圆括号代表参数的部分。
var a = () => 5
相当于
var a = function(){
return 5;
}
(2)箭头函数为多个参数时,也需要用圆括号将所有的参数括起来
var sum = (num1,num2) => num1+num2
相当于
var sum = function(num1.num2){
return num1+num2;
}
1.2 函数体何时加{}和()
上面的例子是箭头函数的函数体为直接返回语句时(return时)。
(1)如果箭头函数的代码块部分多于一条语句,就需要使用大括号将其括起来,并且使用return语句返回。
var mulAndSum = (num1,num2) =>{
let mul1 = num1 * 2
let mul2 = num2 * 3
return mul1+mul2;
}
(2)如果箭头函数直接返回一个对象,必须加上圆括号,否则会报错。
var returnObj = id => {id:id,name:"cjx"} //报错
应写成
var returnObj = id => ({id:id,name:"cjx"})
//试着打印出来看一下
console.log(returnObj(1))
相当于
var returnObj = function(id){
return{
id:id,
name:"cjx"
}
}
//试着打印出来看一下
console.log(returnObj(1))
2. 嵌套的箭头函数
箭头函数内部还可以再使用箭头函数。
//ES5的多重嵌套如下
function insert(value) //(1)insert函数-返回对象
{
return {
into:function(array) //(2)into方法(函数)-返回对象
{
return{
after:function(afterValue) //(3)after方法(函数)-返回数组
{
array.splice(array.indexOf(afterValue)+1, 0, value);
return array;
}
}
}
}
}
console.log(insert(2).into([1, 3]).after(1)); //[1, 2, 3]
这个嵌套比较复杂 我们来缕一下逻辑。
(1)insert这个函数,返回了一个具有into方法的对象,
(2)into这个方法,返回了一个具有after方法的对象,
(3)after这个方法,执行了一段函数体,返回了一个数组。
我们来将以上代码转换成箭头函数,注意以下几点噢~
(1)箭头左边为参数,右边为函数体
(2)若返回是一个对象,必须用()括起来
let insert = value => ({into:(array)=>({after:(afterValue)=>{
array.splice(array.indexOf(afterValue)+1, 0, value)
return array
}})})
console.log(insert(2).into([1,3]).after(1))
是不是乍一眼 一脸懵 我们来试着分步写就很清楚啦~一步一步对应
(1)insert这个函数,返回了一个具有into方法的对象,即
let insert = (参数) => ({into:(2)})
(2)into这个方法,返回了一个具有after方法的对象
into:(参数)=>({after:(3)})
(3)after这个方法,执行了一段函数体,返回了一个数组。
after:(参数)=>{函数体}
这样再把三步合起来就是我们嵌套的箭头函数啦~
3. 箭头函数的注意点!
3.1 this
在ES6中,箭头函数的this不是调用的时候决定的,而是在定义的时候决定的,定义时所在的对象就是它的this。
即,在ES5当中,this是谁调用这个函数,函数的的this就是谁。如
<body>
<button id = "btn1">btn1</button>
<script type="text/javascript">
let btn1 = document.getElementById("btn1")
btn1.onclick = function() { //btn1调用的方法
console.log(this)
}
</script>
</body>
而在ES6中,this是函数定义时所处的对象(我认为是函数定义时所处的对象所指的this?),我们把上面的代码改成箭头函数来看看
<body>
<button id = "btn1">btn1</button>
<script type="text/javascript">
let btn1 = document.getElementById("btn1")
btn1.onclick = ()=> console.log(this) //函数定义时所处的对象。
</script>
</body>
来道网上的面试题来测试一下对箭头函数this的理解
window.color = "red";
let color = "green"; //思考如果这是var定义的时候结果又如何?
let obj = {
color: "blue",
getColor: () => {
return this.color;
}
};
let sayColor = () => {
return this.color;
};
console.log(obj.getColor());
console.log(sayColor());
我们来思考一下这两个打印输出什么呢?
这是由于箭头函数的this在定义的时候就已经被绑定了。当在声明getColor和sayColor时,此时的this指向window。所以输出的为red。
若将这两个箭头函数都改成ES5时的函数声明呢?
getColor打印输出的就是blue了,这是由于这个非箭头函数是obj调用的,这个this就指向了obj。
若将let color = “green“ 改成 var color = ”green“的话。以上输出red的地方都变成了green。因为let 声明的全局变量不具有全局属性,即不能用window.访问
window.color = "red";
var color = "green";
console.log("var:",color)
window.color1 = "blue";
let color1 = "yellow"
console.log("let:",color1)
3.2 this指向的固定化
箭头函数无法使用 call()或 apply()来改变其运行的作用域。
我们再来看一道面试题~
let color = "red";
let obj = {
color: "blue"
};
let sayColor = () => {
return this.color;
};
sayColor.apply(obj);
这个的输出结果应该是什么呢?
输出undefined是由于:
(1)sayColor这个箭头函数在定义的时候this就确定为window了
(2)call()或apply()或bind()没有办法改变箭头函数的this,所以this还是window
(3)由于let声明的全局变量不属于window,而window对象的color属性未定义。所以输出undefined~
3.3 不可以当作构造函数
因为在构造函数中的 this 指向新创建的对象。而箭头函数的this无法指向新创建的对象。所以箭头函数不可以当作构造函数。不可以使用new命令,否则会抛出一个错误。
3.4 不可以使用arguments
在ES5中,我们可以使用arguments来获取参数列表,如下:
function func(){
console.log(arguments)
}
func(1,2,3)
可打印出
但在ES6的箭头函数中,这样是会报错的
var func1 = ()=>{
console.log(arguments)
}
func1()
应当使用rest(剩余运算符)来代替arguments
var func1 = (...rest)=>{
console.log(rest)
}
func1(1,2,3)
3.5 不可以使用yield命令
箭头函数不能当做Generator函数,不能使用yield关键字。
(Generator还没看到,学完了再回来补这~)
3.6 箭头函数不适用场景
(1)由于this指向的原因,箭头函数不适用于定义对象的包含this的方法
(2)需要动态this的时候,也不应使用箭头函数。例如想为用this为按钮添加点击监听事件时。