昨天小编面了一家中小厂,被问到这个问题的时候自我感觉回答的不是太好,对箭头函数了解还不多,被拷打的我立志要把箭头函数搞明白。话不多说,直接开始本期内容。
在ES6之前,函数定义的主要方式我用 function 关键字,就像这样:
function greet(name) {
return `Hello, ${name}!`;
}
这样写虽然没啥问题,但有时候会感觉有点冗长。后来ES6带来了箭头函数,一下子就给函数定义方式带来了新变化。
先看看箭头函数的语法,它非常简洁。如果函数没有参数,那就是一个空括号加箭头,再跟上函数体。比如我们想写一个简单的函数,每次调用都输出一句固定的话:
() => console.log('Welcome to the world of arrow functions!');
要是函数只有一个参数,括号都能省略。比如有个需求,要写一个函数,接收一个数字,然后返回这个数字的平方,用箭头函数就可以这么写:
num => num * num;
当函数有多个参数时,就用括号把参数括起来,中间用逗号隔开。比如写一个函数,接收两个数字,返回它们的和:
(a, b) => a + b;
要是函数体只有一句返回语句,大括号和 return 关键字都可以省略。例如,我们有一个数组,想要过滤掉其中的奇数,保留偶数,用箭头函数结合数组的 filter 方法,代码就可以写成这样:
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // 输出 [2, 4]
箭头函数一个很关键的特性就是它没有自己的 this 。它的 this 是继承自外层作用域的 this ,并且在定义的时候就确定好了,不会改变。这和普通函数可不一样。在普通函数里, this 的指向有时候很难把握。比如在对象方法里,像下面这样:
const person = {
name: 'Alice',
sayHello: function() {
setTimeout(function() {
console.log(`Hello, ${this.name}!`);
}, 1000);
}
};
person.sayHello(); // 这里输出的是 "Hello, undefined!",因为setTimeout里的普通函数的this指向了全局对象
但如果把 setTimeout 里的函数换成箭头函数,情况就不同了:
const person = {
name: 'Bob',
sayHello: function() {
setTimeout(() => {
console.log(`Hello, ${this.name}!`);
}, 1000);
}
};
person.sayHello(); // 这里会输出 "Hello, Bob!",因为箭头函数的this继承了外层的this,也就是person对象
还有,箭头函数没有自己的 arguments 对象。以前在普通函数里, arguments 可以获取到所有传入的参数。在箭头函数里没这玩意儿了,不过我们可以用 rest 参数来替代。比如写一个函数,接收任意多个数字,然后返回它们的总和:
const sum = (...nums) => {
let total = 0;
for (const num of nums) {
total += num;
}
return total;
};
console.log(sum(1, 2, 3)); // 输出 6
当然,箭头函数也不是万能的,它有一些限制。它不能当作构造函数来用,不能用 new 来实例化对象。因为它没有自己的 this 和 prototype 属性。像下面这样就是错误的用法:
const ArrowConstructor = () => {
this.value = 10;
};
const instance = new ArrowConstructor(); // 会报错
而且它也不能使用 yield 关键字,所以没办法用作生成器函数。
在实际的项目开发中,箭头函数的应用场景非常多。比如在使用数组的高阶函数,像 map 、 filter 、 reduce 的时候,用箭头函数会让代码看起来简洁又直观。再比如在事件监听中,用箭头函数也很方便。假设我们要监听一个按钮的点击事件,代码可以写成这样:
<!DOCTYPE html>
<html lang="en">
<body>
<button id="myButton">Click Me</button>
<script>
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log('Button clicked!');
});
</script>
</body>
</html>