我自己是一名从事了多年开发的web前端老程序员,目前辞职在做自己的web前端私人定制课程,今年年初我花了一个月整理了一份最适合2019年学习的web前端学习干货,各种框架都有整理,送给每一位前端小伙伴,想要获取的可以关注我的头条号并在后台私信我:前端,即可免费获取。
为了保证的可读性,本文采用意译而非直译。
这些年来,ES6 将 JS 的可用性提升到一个新的水平时: 箭头函数、类等等,这些都很棒。
箭头函数是最有价值的新功能之一,有很多好文章描述了它的上下文透明性和简短的语法。
但每个事务都有两面。通常,新特性会带来一些混乱,其中之一就是箭头函数被误导了。本文将介绍一些场景,在这些场景中,你应该绕过箭头函数,转而使用良好的旧函数表达式或较新的简写语法。并且要注意缩短代码,因为这会影响代码的可读性。
1.定义对象上的方法
在JavaScript中,方法是存储在对象属性中的函数。当调用该方法时, this 将指向该方法所属的对象。
Object literal
由于箭头函数有一个语法简短,所以使用它来定义方法是很有吸引力的,让我们试一试:
![73ea5aa4cedcfa88cd2a2ebed121a004.png](https://i-blog.csdnimg.cn/blog_migrate/06dc0a247ffc33ebbf3cbacd7a11291c.jpeg)
calculate.sum方法用箭头函数定义。但是在调用时, calculate.sum() 会抛出一个 TypeError,因为 this.array 为 undefined。
当调用 calculate对象上的方法 sum()时,上下文仍然是 window。之所以会发生这种情况,是因为箭头函数按词法作用域将上下文绑定到 window 对象。
执行 this.array等同于 window.array,它是 undefined。
解决方法是使用通常函数表达式来定义方法。this 是在调用时确定的,而不是由封闭的上下文决定的,来看看修复后的版本:
![695c1316b673aaa645f1513bd46b73ba.png](https://i-blog.csdnimg.cn/blog_migrate/d3f69e127b8d9b95393b2e29c9d96356.jpeg)
因为 sum是常规函数,所以在调用 calculate.sum() 时 this 是 calculate 对象。 this.array是数组引用,因此正确计算元素之和: 6。
Object prototype
同样的规则也适用于在原型对象上定义方法。使用一个箭头函数来定义 sayCatName方法, this 指向 window
![a09cad59ce4da01e089927a6c3906a35.png](https://i-blog.csdnimg.cn/blog_migrate/44478e2fb57d0d2f9f62edcc63b88b1b.jpeg)
使用早期的方式定义函数表达式:
![daf1229fed6dcead87c1419e5e49a775.png](https://i-blog.csdnimg.cn/blog_migrate/61cc226cba4df50a44d89eb9ed853954.jpeg)
sayCatName常规函数在作为方法调用时将上下文更改为 cat对象: cat.sayCatName()。
2. 动态上下文的回调函数
this 在JS中是一个强大的特性,它允许根据调用函数的方式更改上下文。通常,上下文是调用发生的目标对象,这使得代码更加自然,就像这个物体发生了什么。
但是,箭头函数会在声明上静态绑定上下文,并且无法使其动态化,但这种方式有坏也有好,有时候我们需要动态绑定。
在客户端编程中,将事件侦听器附加到DOM元素是一项常见的任务。事件触发处理程序函数,并将 this作为目标元素,这里如果使用箭头函数就不够灵活。
下面的示例尝试为这样的处理程序使用箭头函数:
![53911de99bd019d5c1d7ed61945273f5.png](https://i-blog.csdnimg.cn/blog_migrate/9e758d74925eae3553b87214c8811776.jpeg)
在全局上下文中 this 指向 window。当发生单击事件时,浏览器尝试使用按钮上下文调用处理函数,但箭头函数不会更改其预定义的上下文。 this.innerHTML相当于 window.innerHTML,没有任何意义。
必须应用函数表达式,该表达式允许根据目标元素更改 this:
![c915a8ea4f727a06dbe1aa62b255aeef.png](https://i-blog.csdnimg.cn/blog_migrate/8df6fc908b0182f6a6b0305110312ca6.jpeg)
当用户单击按钮时,处理程序函数中的 this 指向 button。因此这个问题。innerHTML = '已单击按钮'正确地修改按钮文本以反映已单击状态。
3.调用构造函数
this 在构造调用中是新创建的对象。当执行 newMyFunction()时,构造函数 MyFunction的上下文是一个新对象: thisinstanceofMyFunction===true。
注意,箭头函数不能用作构造函数。JavaScript通过抛出异常隐式阻止这样做。
无论如何, this是来自封闭上下文的设置,而不是新创建的对象。换句话说,箭头函数构造函数调用没有意义,而且是模糊的。
让我们看看如果尝试这样做会发生什么:
![bebe85a8c03537c1b43c0e7335485a45.png](https://i-blog.csdnimg.cn/blog_migrate/757e4d8574455da63631c33a65005df3.jpeg)
执行 newMessage('Hello World!'),其中 Message是一个箭头函数,JavaScript抛出一个 TypeError 错误, Message不能用作构造函数。
上面的例子可以使用函数表达式来修复,这是创建构造函数的正确方法(包括函数声明):
![5d4d2a17cafe83b0380ff581110ae8b6.png](https://i-blog.csdnimg.cn/blog_migrate/a609caf1ad50ae8945a6d577919ad1df.jpeg)
简写语法
箭头函数有一个很好的属性,它可以省略参数圆括号 ()、块大括号 {},如果函数主体只有一条语句,则返回。这有助于编写非常短的函数。
作者的大学编程教授给学生一个有趣的任务:编写 用C语言计算字符串长度的最短函数,这是学习和探索新语言的好方式。
然而,在实际应用程序中,许多开发人员都会阅读代码。最短的语法并不总是适合帮助你的同事即时了解该方法的用途。
在某种程度上,简写的函数变得难以阅读,所以尽量不要过度wfget。让我们看一个例子
![00791029fcd05b2ff230396ec444b02d.png](https://i-blog.csdnimg.cn/blog_migrate/ad4531bff0c0f2776b8c03920303070c.jpeg)
multiply返回两个数字的乘法结果或与第一个参数绑定的闭包,以便以后的乘法运算。
该函数运行良好,看起来很短。但从一开始就很难理解它是做什么的。
为了使其更具可读性,可以从箭头函数恢复可选花括号和 return语句,或使用常规函数:
![60021141c7e793f261b71071e1764059.png](https://i-blog.csdnimg.cn/blog_migrate/b4a4e41cda793d3ed9a79a31d3b0e130.jpeg)
在简短和冗长之间找到一个平衡点是很好的,这样可以使代码更加直观。
总结
毫无疑问,箭头函数是一个很好的补充。当正确使用时,它会使前面必须使用 .bind()或试图捕获上下文的地方变得简单,它还简化了代码。
某些情况下的优点会给其他情况带来不利。当需要动态上下文时,不能使用箭头函数:定义方法,使用构造函数创建对象,在处理事件时从 this 获取目标。
原文:https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/
译者:前端小智