持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 1 天,点击查看活动详情
箭头函数,相信大家经常在使用,其简洁的写法获得了不少开发者喜爱, 今天就在复习箭头函数相关知识,记录学习笔记,有不足之处希望掘友们能够帮忙指出,感谢大家!
语法
先回顾一下箭头函数的语法,有一些需要注意的地方:
// 当只有一个参数时,括号可以省略,其他情况不能省略
var func = () => { ... };
var func = p => { ... };
var func = (p1, p2) => { ... };
// 当返回值是一个表达式,可以省略 {} 与 return
var func = (p1, p2) => p1 + p2;
// 其他情况不能省略 {} 与 return
var func = (p1, p2) => {
const sum = p1 + p2;
return sum;
};
// 请注意,如果返回值是一个对象,需要用 () 包裹对象
var func = p => { foo: p }; ❌
var func = p => ({ foo: p}); ✔
// 与常规函数不同的特殊运算符优先级解析规则
callback = callback || () => {}; ❌
callback = callback || (() => {}); ✔
// 箭头函数在参数和箭头之间不能换行
var func = ()
=> 1; ❌
// 但是,可以在 ‘=>’ 之后换行
var func = (a, b, c) =>
1;
特点
this
箭头函数内部的 this 是词法作用域,由上下文确定。
箭头函数不会自己创建
this,它只会从自己的作用域链的上一层继承this。 - MDN
这样对于我们开发有什么好处呢?长期以来,JavaScript 的 this 指向一直令人头疼,一旦处理不好将会带来很多问题。要处理函数中 this 的指向,以前都用那种 hack 写法:
var obj = {
birth: 1990,
getAge: function () {
var that = this; // this指向obj对象
var b = this.birth; // 1990
var fn = function () {
// 这里的this会指向window,所以要用that
return new Date().getFullYear() - that.birth;
};
return fn();
},
};
obj.getAge(); // 25
但是有箭头函数以后这种写法就不再需要了
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth; // 1990
var fn = () => new Date().getFullYear() - this.birth;
return fn();
},
};
obj.getAge(); // 25
这种写法更加简洁,并且 this 的指向一目了然,不需要自己来控制。
new、super 和 new.target
箭头函数没有自己的 this ,不能用作构造函数,也就是无法使用 new 关键字,具体原因可以看看Jokerrr的这篇文章。因为无法作为构造函数,所以 super 和 new.target 自然也不存在。
arguments
箭头函数不绑定 arguments ,所以也不存在 arguments 下的所有属性。如果需要类似实现,可以使用 剩余参数 来代替:
var func = (...args) => {
console.log(args);
};
func(1, 2, 3); // [1, 2, 3]
call、apply 和 bind
因为箭头函数中的 this ,已经按照词法作用域绑定了,所以就算调用 call()、apply() 或 bind(),也无法改变 this 的指向。
由于箭头函数没有自己的
this,通过call()、apply()或bind()方法调用时,只能传递参数,它们的第一个参数会被忽略。- MDN
var obj = {
msg: "obj",
};
var func = (...args) => {
console.log(this.msg);
console.log(args);
};
// 第一个参数将被忽略
func.call(obj); // undefined
// []
func.call(obj, obj); // undefined
// [{ msg: "obj" }]
yield
不能在箭头函数中使用 yield 关键字,因此箭头函数无法作为函数生成器(Generator)。
但是在MDN中有提到说:
yield关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)
文档这里说的除非这个情况目前暂时没有遇过,尝试写了一下会报错,可能是写法不对,请掘友大佬们康康什么情况
function* generotor() {
yield 1;
yield 2;
yield 3;
const func = () => {
yield 4;
};
func();
}
// Uncaught SyntaxError: Unexpected number
使用
箭头函数表达式适合作为非方法函数使用,作为方法使用时需要注意下面的情况:
var obj = {
num: 18,
getNum: () => console.log(this.num, this),
getNum2: function () {
console.log(this.num, this);
},
};
obj.getNum(); // undefined, Window {...}
obj.getNum2(); // 18, Object {...}
出现比较多的地方是在回调函数中,尤其是数组相关的方法:
var arr = [5, 2, 6, 1];
arr.sort((a, b) => a - b);
console.log(arr); // [1, 2, 5, 6]
作为闭包使用:
var Add = (i = 0) => () => (++i);
var a = Add();
var b = Add();
a(); // 1
a(); // 2
b(); // 1
a(); // 3
b(); // 2
总结
- 箭头函数指向的是上下文的
this,并且无法改变,即使使用call()、apply()或bind()。 - 无法作为构造函数和函数生成器使用,也不存在
prototype属性。