作者:Dmitri Pavlutin
译者:前端小智
来源:dmitripavlutin.com
箭头功能值得流行。 它的语法简洁明了,使用词法绑定绑定 this,它非常适合作为回调。在本文中,通过了解决学习5个最佳实践,以便我们可以从中学习更多箭头函数的知识,并从它身上获得更多的好处。
JS 中的箭头函数是匿名(anonymous)的:函数的name属性是''。
( number => number + 1 ).name; // => ''
在调试会话或调用堆栈分析期间,匿名函数被标记为anonymous。 不幸的是,anonymous程序不提供有关正在执行的代码的任何线索。
这里是执行匿名函数的代码的调试会话:
右边的调用堆栈由两个标记为anonymous的函数组成,我们无法从这样的调用堆栈信息中获得任何有用的信息。
幸运的是,函数名推断(ES2015的功能)可以在某些条件下检测到函数名称。 名称推断的思想是JS 可以从其语法位置确定箭头函数名称: 从保存函数对象的变量名称中获取。
我们来看看函数名称推断的工作原理:
const increaseNumber = number => number + 1;
increaseNumber.name; // => 'increaseNumber'
因为变量increaseNumber保存了箭头函数,所以 JS 决定使用increaseNumber作为该函数的名称。因此,箭头函数的名称为 'increaseNumber'。
第1个实践:
一个好的做法是使用函数名称推断来命名箭头函数。
现在我们用使用名称推断的代码检查一个调试会话:
因为箭头函数有名称,所以调用堆栈提供了有关正在执行的代码的更多信息。
内联函数是仅具有一个表达式的函数。 我喜欢箭头功能,可以编写短内联函数。
例如,不要使用箭头函数的长形式:
const array = [1, 2, 3];
array.map((number) => {
return number * 2;
});
当箭头函数只有一个表达式时,可以轻松地删除大括号{}和return语句:
const array = [1, 2, 3];
array.map(number => number * 2);
第2个实践:
当函数只有一个表达式时,一个好的做法是使用内联箭头函数格式
比较操作符>、<、<=和>=看起来类似于f胖箭头=>(它定义了箭头函数)。当在内联箭头函数中使用这些比较操作符时,会产生一些混淆。
例如我们定义一个使用<=操作符的箭头函数
const negativeToZero = number => number <= 0 ? 0 : number;
同一行上的两个符号=>和<=的存在会引起误解。
为了清楚地将胖箭头与比较操作符区分开,我们可以使用圆括号:
const negativeToZero = number => (number <= 0 ? 0 : number);
第二个选项是使用更长的形式来定义箭头函数:
const negativeToZero = number => {
return number <= 0 ? 0 : number;
};
这些重构消除了胖箭头符号和比较操作符之间的混淆。
第3个实践:
如果箭头函数包含操作符>、<、<=和>=,一个好的做法是将表达式包装成一对括号,或者故意使用更长的箭头函数形式。
在内联箭头函数中使用对象字面量会触发语法错误:
const array = [1, 2, 3];
// throws SyntaxError!
array.map(number => { 'number': number });
JS 认为花括号是代码块,而不是对象文字。
将对象字面量加上一对括号即可解决此问题:
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'
}));
第4个实践:
在内联箭头函数中使用对象时,把改对象包装在一对括号中。
箭头函数的语法很短,很好。 但是,副作用是,当许多箭头函数嵌套时,它可能是晦涩难懂。
我们考虑以下情况。 单击按钮后,启动对服务器的请求,响应准备就绪后,将各项记录到控制台:
myButton.addEventListener('click', () => {
fetch('/items.json')
.then(response => response.json());
.then(json => {
json.forEach(item => {
console.log(item.name);
});
});
});
这里有三层箭头函数的嵌套,需要花时间和精力来了解代码的作用。
为了提高嵌套函数的可读性,第一种方法是引入每个包含箭头函数的变量,该变量应简明地描述函数的功能。
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);
第5个实践:
避免箭头函数过多的嵌套,好的做法是通过将箭头函数提取为独立函数,或者尽可能使用async/await语法。
JS中的箭头函数是匿名的。为了使调试更高效,一个好的实践是使用变量来保存箭头函数,这允许JS 推断函数名。
当函数主体具有一个表达式时,嵌入式箭头函数非常方便。
操作符>、<、<=和>=看起来类似于胖箭头=>,在内联箭头函数中使用这些操作符时必须小心。
对象字面量语法{prop:'value'}与代码块{}相似。 因此,当将对象字面量放置在嵌入式箭头函数中时,需要将其包装在一对括号中:()=>({prop:'value'})。
最后,函数的过度嵌套模糊了代码意图。减少箭头函数嵌套的一个好方法是将它们提取到变量中。或者,尝试使用更好的特性,如async/await语法。
ES6中允许使用箭头=>来定义箭头函数,具体语法,我们来看一个简单的例子:以看出,定义箭头函在数语法上要比普通函数简洁得多。箭头函数省去了function关键字,采用箭头=>来定义函数。函数的参数放在=>前面的括号中,函数体跟在=>后的花括号中。
传统的javascript函数语法并没有提供任何的灵活性,每一次你需要定义一个函数时,你都必须输入function () {},这至少会出现两个问题,ES6箭头函数都圆满解决了它,箭头函数内的this值继承自外围作用域。运行时它会首先到它的父作用域找,如果父作用域还是箭头函数
这些年来,ES6 将 JS 的可用性提升到一个新的水平时: 箭头函数、类等等,这些都很棒。箭头函数是最有价值的新功能之一,有很多好文章描述了它的上下文透明性和简短的语法。
ES6中允许使用箭头=>来定义箭头函数,是ES6中较受欢迎也较常使用的新增特性。本文将从箭头函数的基本语法,与普通函数对比,箭头函数不适用场景三个方面进行梳理。
在箭头函数出现之前,每个新定义的函数都有它自己的this值(在构造函数的情况下是一个新对象,在严格模式的函数调用中为underfined,如果该函数被作为”对象方法“调用则为基础对象等)。This被证明是令人厌烦的面向对象风格的编程。
虽然两者的语法都能够定义函数,但是在开发时该怎么选择呢?这是个好问题。在本文中,我将展示两者之间的主要区别,以供你能够根据需要选择正确的语法。
但每个事务都有两面。通常,新特性会带来一些混乱,其中之一就是箭头函数被误导了。本文将介绍一些场景,在这些场景中,你应该绕过箭头函数,转而使用良好的旧函数表达式或较新的简写语
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!