作者简介:
李中凯
八年多工作经验 前端负责人,
擅长JavaScript/Vue。
掘金文章专栏:https://juejin.im/user/57c7cb8a0a2b58006b1b8666/posts
公众号:1024译站
箭头函数以其简洁的语法、没有烦人的this
问题而广受欢迎,非常适合用作回调函数。
本文将介绍5个最佳实践方法,帮你用好箭头函数。
1箭头函数名称推断
JavaScript 中的箭头函数是匿名函数:函数的name
属性是空字符串''
。
( number => number + 1 ).name; // => ''
匿名函数在调试过程中和调用栈分析里被标记为anonymous
。很遗憾,anonymous
对执行中的代码没有提供任何追踪信息。
下面是代码中执行匿名函数的调试截图:
image右边的调用栈包含2个标记为anonymous
的函数。从这样的调用栈里你无法得到任何有用的信息。
所幸的是,函数名称推断(ES2015 的特性)可以在特定条件下检测到函数名称。名称推断是指,JavaScript 可以从其语法位置确定箭头函数名:例如,从指向函数对象的变量名得到。
我们来看看函数名称推断是怎么工作的:
const increaseNumber = number => number + 1;increaseNumber.name; // => 'increaseNumber'
由于变量 increaseNumber
指向这个箭头函数,JavaScript 就认为 'increaseNumber'
可以作为这个函数的名称。
现在我们来看使用了名称推断后的调试过程:
image因为箭头函数有名称了,调用栈就可以给出运行中的代码的更多信息:
-
handleButtonClick
这个函数名称表明某个点击事件被触发了 -
increaseCounter
增加计数器变量
2尽量使用内联形式
内联函数是只有一个表达式的函数。我比较喜欢箭头函数的内联形式。
例如,不使用完整形式的箭头函数:
const array = [1, 2, 3];array.map((number) => { return number * 2;});
而是去掉花括号{ }
和return
语句,只保留一个表达式:
const array = [1, 2, 3];array.map(number => number * 2);
我的建议是:
当函数只有一个表达式时,尽量使用内联形式
3当箭头符号遇上比较符号
用于比较的运算符 >
,<
,<=
和 >=
看起来跟箭头符号=>
很像,这些符号用在内联箭头函数里面容易造成混淆,影响阅读。
比如这个:
const negativeToZero = number => number <= 0 ? 0 : number;
=>
和<=
这两个符号出现在同一行里可能会误导人。
为了清楚地区分这两个符号,第一种做法是用圆括号把表达式括起来:
const negativeToZero = number => (number <= 0 ? 0 : number);
第二种做法是刻意使用完整形式的箭头函数:
const negativeToZero = number => { return number <= 0 ? 0 : number;};
这样箭头符号和比较符号就不容易混淆了。
4内联表达式与对象字面量
内联箭头函数里的对象字面量这样写会导致语法错误:
const array = [1, 2, 3];// throws SyntaxError!array.map(number => { 'number': number });
JavaScript 认为这里的花括号是代码块,而不是对象字面量。如果是这种情况,怎么在内联表达式里返回对象字面量呢?外面加一层圆括号就行了:
const array = [1, 2, 3];// Works!array.map(number => ({ 'number': number }));
如果对象字面量有很多个属性,你可以每行写一个,这样保持内联形式的同时,可读性更好:
const array = [1, 2, 3];// Works!array.map(number => ({ 'number': number 'propA': 'value A', 'propB': 'value B'}));
5减少多层嵌套
箭头函数语法简洁,这个很好。但是也有副作用,就是容易写成多层嵌套,这样就会导致类似“回调地狱”的问题。
来看下面这个例子:
myButton.addEventListener('click', () => { fetch('/items.json') .then(response => response.json()); .then(json => { json.forEach(item => { console.log(item.name); }); });});
嵌套了3层箭头函数,要理解代码的意图就比较吃力和费时。
为了提高嵌套函数的可读性,第一种方法是给每个箭头函数指定一个变量。这些变量需要准确描述函数的功能。
const readItemsJson = json => { json.forEach(item => console.log(item.name));};const handleButtonClick = () => { fetch('/items.json') .then(response => response.json()); .then(readItemsJson);};myButton.addEventListener('click', handleButtonClick);
重构后的代码把箭头函数提取到了 readItemsJson
和handleButtonClick
变量中。嵌套由3层降低到2层,现在就更容易理解代码的意图了。
甚至更进一步,你可以用async/await
语法重构整个函数,这样彻底不需要嵌套了:
const handleButtonClick = async () => { const response = await fetch('/items.json'); const json = await response.json(); json.forEach(item => console.log(item.name));};myButton.addEventListener('click', handleButtonClick);
作者简介:
李中凯
八年多工作经验 前端负责人,
擅长JavaScript/Vue。
掘金文章专栏:https://juejin.im/user/57c7cb8a0a2b58006b1b8666/posts
公众号:1024译站
本文已经获得李中凯老师授权转发,其他人若有兴趣转载,请直接联系作者授权。
网友评论