面试官: 箭头函数你了解多少啊?看完的你:死歌开大,直接开始吟唱😂

129 阅读2分钟

昨天小编面了一家中小厂,被问到这个问题的时候自我感觉回答的不是太好,对箭头函数了解还不多,被拷打的我立志要把箭头函数搞明白。话不多说,直接开始本期内容。

在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>