Photo by Andrew Worley on Unsplash

原文链接:9 Tricks for Kickass JavaScript Developers in 2019
原文作者:Lukas Gisder-Dubé
译者:JintNiu
推荐理由:JavaScript 已经成为了当今使用最为广泛、最受欢迎的语言之一,掌握一些使用技巧不仅可以提高开发效率,更有利于思维转换。


过去的一年, JavaScript 在持续变化着,其使用范围也越来越广。接下来,我将针对 JavaScript 的使用,列出 9 条 建议,以帮助你写出更加整洁高效的代码,成为更好的开发者。

1. async/await

JavaScript 极速发展的今天,回调地狱所产生的问题已不复存在。实际开发过程中我们应当尽量避免使用回调函数,除非为了遵守代码库规则或是维护性能。而解决回调地狱的一个常用方法为 Promise,但在代码量较多时使用会适得其反。于是提出了 async / await,使代码结构更加清晰明了,便于阅读和维护。一般而言,可以 await 任何 Promise 以防止正使用的库的返回值为 Promise ,也就是说 async/awaitPromise 的语法糖,而且使用方法也十分简单:在函数前加 async。下面是一个简单的例子:

async function getData() {const result = await axios.get('https://dube.io/service/ping')const data = result.dataconsole.log('data', data)return data
}
getData()
复制代码

await 只能使用在 async 函数中,不能用于全局作用域。

async/await 是 ES2017 中引入的,使用时请进行转换。

2. 异步控制流

当我们进行异步调用并获得返回值时,通常期望直接获取多个数据集,并且分别操作每个数据集。因此有了以下方式:

for...of

假设页面上要展示 Pokemon 数据,可以通过 axios 获取它们的详细信息,我们所期望的是在得到返回值时立即更新页面中的所有数据,而不是等所有调用完成后才进行更新。

我们可以使用 for...of 解决上述问题。 首先循环遍历数组,并在每个循环内执行异步代码,当所有调用都成功时跳出循环。需要注意的是,这种方法虽然会对性能产生一些影响,但也不乏是一个很好的方法。

以下是一个例子:

import axios from 'axios'let myData = [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }]async function fetchData(dataSet) {for (entry of dataSet) {const result = await axios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)const newData = result.dataupdateData(newData)console.log(myData)}
}
function updateData(newData) {myData = myData.map(el => {if (el.id === newData.id) return newDatareturn el})
}
fetchData(myData)
复制代码

可以将这些例子复制粘贴到编辑器中调试运行。

译者注:除了循环本身带来的性能问题之外,在使用 async/await 处理异步请求时也会对性能造成影响:如果使用过多 await 语句,而且候这些语句并不需要依赖于之前的语句,则会产生 async/await 地狱,影响性能。

Promise.all

如果想要并行获取所有的 Pokemon,我们可以使用 Promise.all 方法来 await 所有 Promise


import axios from 'axios'let myData = [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }]
async function fetchData(dataSet) {const pokemonPromises = dataSet.map(entry => {return axios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)})const results = await Promise.all(pokemonPromises)results.forEach(result => {updateData(result.data)})console.log(myData)
}
function updateData(newData) {myData = myData.map(el => {if (el.id === newData.id) return newDatareturn el})
}
fetchData(myData) 复制代码

for...ofPromise.all 都是 ES6+ 引入的,使用时请进行转换。

3. 解构赋值 & 默认值

回到上个例子:

const result = axios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)
const data = result.data
复制代码

现在有一种更简单的方法来实现它:通过解构赋值的方式从对象或数组中获取一个或多个值:

const { data } = await axios.get(...)
复制代码

也可对变量重命名:

const { data: newData } = await axios.get(...)
复制代码

另一种方法是在解构赋值时指定默认值,这样做可以确保代码不会出现 undefined,也避免手动检查变量的麻烦。

const { id = 5 } = {}
console.log(id) // 5
复制代码

这些方法也可以用于函数参数,例如:

function calculate({ operands = [1, 2], type = 'addition' } = {}) {return operands.reduce((acc, val) => {switch (type) {case 'addition':return acc + valcase 'subtraction':return acc - valcase 'multiplication':return acc * valcase 'division':return acc / val}}, ['addition', 'subtraction'].includes(type) ? 0 : 1)
}
console.log(calculate()) // 3
console.log(calculate({ type: 'division' })) // 0.5
console.log(calculate({ operands: [2, 3, 4], type: 'multiplication' })) // 24
复制代码

ES6 引入了解构赋值和默认值,使用时请进行转换。

4. 真值和虚值

当我们使用默认值时,通常要对现有值进行一系列判断,这种方法使代码变得异常繁琐,而现在我们可以真值(Truthy)和虚值(Falsy)的方式来改进它,不仅可以节省代码量,还使人更加信服。

以下是之前的做法:

if (myBool === true) {console.log(...)
}
// OR
if (myString.length > 0) {console.log(...)
}
// OR
if (isNaN(myNumber)) {console.log(...)
}
复制代码

简化后:

if (myBool) {console.log(...)
}
// OR
if (myString) {console.log(...)
}
// OR
if (!myNumber) {console.log(...)
}
复制代码

以下为 FalsyTruthy 的概念:

Falsy

  • 长度为0的字符串
  • 数字 0
  • false
  • undefined
  • null
  • NaN

Truthy

  • 空数组
  • 空对象
  • 其他

使用真值和虚值时没有确切的比较方式,这类似于我们进行比较时常使用双等号 == 而不是三等号 ===。一般而言,这两者的判定方式相同,但在某些情况下也会遇到一些错误,对我来说主要为数字 0

Photo by Philippe Leone on Unsplash

5. 逻辑运算符和三元运算符

逻辑运算符和三元运算符主要用于精简代码,有助于保持代码整洁度,但当他们形成运算链时会显得杂乱。

逻辑运算符

逻辑运算符:和(&&)、或(||),一般用于比较两个表达式,返回值为: truefalse 或着它的匹配值。如下例:

console.log(true && true) // true
console.log(false && true) // false
console.log(true && false) // false
console.log(false && false) // false
console.log(true || true) // true
console.log(true || false) // true
console.log(false || true) // true
console.log(false || false) // false
复制代码

我们可以将逻辑运算符与真值和虚值的相关知识结合起来。

如果有表达式 AB,针对两种逻辑运算符,有以下规则:

  • A && B : 当 Afalse 时则直接返回 A 的值 ;否则返回 B 的值。
  • A || B : 当 Atrue 时则直接返回 A 的值 ;否则返回 B 的值。

译者注:上述规则为逻辑运算中的短路现象。

console.log(0 && { a: 1 }) // 0
console.log(false && 'a') // false
console.log('2' && 5) // 5
console.log([] || false) // []
console.log(NaN || null) // null
console.log(true || 'a') // true
复制代码

三元运算符

三元运算符与逻辑运算符非常相似,但有由三个部分组成:

  1. 条件表达式:其结果为真值或是虚值
  2. 返回值 1:条件表达式为真值时,返回该值
  3. 返回值 2:条件表达式为虚值时,返回该值

例如:

const lang = 'German'
console.log(lang === 'German' ? 'Hallo' : 'Hello') // Hallo
console.log(lang ? 'Ja' : 'Yes') // Ja
console.log(lang === 'French' ? 'Bon soir' : 'Good evening') // Good eveing
复制代码

6. 自判断链接

当访问某个嵌套对象的属性时,由于不能确定目标对象或者属性性是否存在,而需要进行一系列判断:

let data
if (myObj && myObj.firstProp && myObj.firstProp.secondProp && myObj.firstProp.secondProp.actualData)data = myObj.firstProp.secondProp.actualData
复制代码

显而易见,代码变得非常臃肿难看。而自判断链接(optional chaining)的提出,正好可以满足对嵌套属性的校验需求,并使代码更加清晰整洁。如下例:

const data = myObj?.firstProp?.secondProp?.actualData
复制代码

译者注:自判断链接: 检查一个对象上面是否存在某属性。
出现原因:调用某 Object属性链中的某个属性时,如果该属性不存在,会导致 Cannot read property xxx of undefined 错误。于是自判断链接 ?. 出现。
使用方式:obj?.a?.b?.c。依次对代码中的属性进行判断,如果为 null 或者 undefined 时,结束调用,返回 undefined

目前,自判断链接还未纳入官方规范中,只处于第一阶段的实验特性。您需要在 babelrc 中添加 @ babel / plugin-proposal-optional-chaining 后方可使用它。

7. 类属性 & 绑定

JavaScript 中经常会用到绑定(bind)。ES6 规范中箭头函数的引入,使 JavaScript 开发人员有了一种将函数自动绑定到执行上下文中的常用方法,同时这种方法非常重要。

由于 JavaScript 中的类方法有特定的调用方式,因此当我们首次声明一个类时不能使用箭头函数,因此需要在其他位置进行函数绑定,比如在构造函数中(以 React.js 为例)。工作当中我总是先定义类方法再对其进行绑定,这种方法非常繁琐且容易出错。但如果使用 class 语法,我们可以通过箭头函数自动绑定它。以下是绑定 _increaseCount 的例子:

 class Counter extends React.Component {constructor(props) {super(props)this.state = { count: 0 }}render() {return (<div><h1>{this.state.count}</h1><button onClick={this._increaseCount}>Increase Count</button></div>)}_increaseCount = () => {this.setState({ count: this.state.count + 1 })}
}
复制代码

目前,类属性还未纳入官方规范中,只处于第三阶段的实验特性。您需要在 babelrc 中添加 @ babel / plugin-proposal-class-properties 后方可使用。

8. 使用 ParcelJS

作为前端开发人员,保证会有打包项目或着转换代码的需求,对此,webpack 已经在很久之前提出先关规范了。第一次使用 webpack v1.0 时,我花了很长时间进行配置,虽然最终运行成功,但整个过程非常痛苦,而且成功后的我变得畏手畏脚,生怕破坏之前的配置。直到几个月前,ParcelJS 的发现使我心情大好,在提供开箱即用功能的同时,它还实现了按需配置,也可以支持类似于 webpack 或 babel 的插件系统,最重要的是它的速度极快。

译者注:ParcelJS 官网显示,parcelJS 的打包速度比 webpack 快 2 倍以上。

9. 封装自己的组件库

这是一个非常有趣的话题,关于它我有很多的想法。对于 CSS,很多人更倾向于使用类似于 BootStrap 这样的组件库。而对于 JavaScript,仍然有人调用 jQuery 或者其他库来实现验证、滑块等功能。首先不否认使用各种库的好处,但还是强烈建议可以亲手实现这些功能,而不是盲目地安装 npm 包。当整个团队正构建一个类似于 moment.js 或 react-datepicker 的大型库(甚至框架)时,你没必要亲手实现它,但可以封装为属于自己的组件库,而且在实现组件库的同时,您可以:

  1. 准确掌握代码的结构以及运行机制
  2. 真正理解编程及其工作原理
  3. 防止代码库变得臃肿

直接使用 npm 包是当然非常容易,但如果想要实现某些 npm 包中不具备的功能时则会需要更多的时间:如果软件没有按预期正常工作,或者要将其转换为另一个软件包,您将会花费更多时间来了解其 API 的配置方式。因此,您可以为自己量身定做一套数据自己的组件库。


关于作者:Lukas Gisder-Dubé 组件并领导了一家初创公司,期间建立了自己的技术团队,并任职 CTO 一年半。 离开创业公司后,在 Ironhack 担任首席讲师。如今在柏林正建立一家创业咨询公司。查看 dube.io 以了解更多信息。


翻译参考

  1. 怎样处理 async/await 浪费性能问题
  2. Async/Await 优于 Promise 的 6 个理由
  3. MDN - Falsy
  4. MDN - Truthy
  5. Optional Chaining for JavaScript

转载于:https://juejin.im/post/5c4506c9e51d45524c7cf206

[译] 优秀 JavaScript 开发人员应掌握的 9 个技巧相关推荐

  1. [译]优秀的开发人员是培养出来的,不是招聘过来的

    译者:baiyutang 作者:Eduards Sizovs 招聘市场上,每一家公司都在寻找技术最优秀的人才.这些公司都在等着天才工程师会从不知道什么地方突然出现,就好像哪里有什么天才秘密工厂似的.这 ...

  2. 好的JavaScript开发人员关键看哪里

    遥想当年还年少的时候,我的兴趣爱好就跨越了各种不相关的领域.我喜欢数学,如同我深爱历史那样.我的目标是成为像文艺复兴时期多才多艺的伟人那样--在多个领域都有出色表现.这是一个艰巨的任务--突然之间我发 ...

  3. 面向JavaScript开发人员的Adobe AIR与Dreamweaver

    入门教程,非常详细,CS4里面应该可以省略前面几步直接开发了. Adobe AIR对于HTML/JavaScript应用程序与桌面的集成有着出色的支持,但除了所有附加功能之外,还需要一些其他工具和技术 ...

  4. ​JavaScript 开发人员的主要基本技能是?

    程序员之所以欣赏JavaScript软件开发,是因为他们能够利用JavaScript构建客户喜欢的高度互动网站. 作者 | PaulAzorín 译者 | 弯月,责编 | 刘静 出品 | CSDN(I ...

  5. 做一名优秀的软件开发qa_如何成为一名优秀的开发人员

    做一名优秀的软件开发qa As a PHP developer, or any kind of developer as a matter of fact, you need to constantl ...

  6. This is why you never end up hiring good developers 这就是为什么你永远招不到优秀的开发人员

    中文为我的译文,英文为原文 英文原文地址:http://qz.com/258066/this-is-why-you-dont-hire-good-developers/ 这就是为什么你永远招不到优秀的 ...

  7. 业余软件开发_我需要在业余时间编码才能成为一名优秀的开发人员

    业余软件开发 "You need to code in your spare time to be a good developer" - I've been hearing th ...

  8. dart参数传方法_为 JavaScript 开发人员准备的 Dart 参考教程

    Dart 是 Flutter 主要的开发语言,这一篇文章主要为 JavaScript 开发人员准备的 Dart 教程,我会用很详细的对比来参考,力争 JavaScript 开发人员可以快速的熟练使用 ...

  9. 成为更优秀的开发人员:第一步-“制造”粉丝

    编者按:原文作者罗布·沃林(Rob Walling)从事Web应用开发10年之久,担任过业内顾问.自由开发人员和全球最大的信用卡预付公司City of Pasadena的开发经理.现居住于加州中部城市 ...

最新文章

  1. MySQL(MariaDB)常用DOM命令
  2. 在DataGrid(WebControl)中处理DropDownList事件的补充说明
  3. linux I/O--五种I/O模型(一)
  4. python处理csv文件缺失值_Python:如何处理CSV中的缺失值?
  5. Mybatis中的jdbcType的作用
  6. @transaction使自定义注解失效_【完美】SpringBoot中使用注解来实现 Redis 分布式锁...
  7. 码云 Gitee 新增仓库访问之 IP 白名单功能
  8. 计算机基础知识表格加密管理,【事业单位考试】计算机网络知识:数据加密技术之密钥管理...
  9. 【ASP.NET Step by Step】之十六至二十三 Inserting, Updating, and Deleting Data
  10. 计算机基础函数运用,计算机应用基础第十二讲:EXCEL中函数的实际运用.doc
  11. 【Android开发】【数据库】Realm For Android
  12. P3160 [CQOI2012]局部极小值
  13. 有道智云智能语音服务全面升级 最多可支持44种语言和方言
  14. 你写得API接口代码真是一坨屎,难道不能对返回格式统一处理一下吗?
  15. cad填充图案乱理石_「AutoCAD之填充」CAD图案填充的6个要点以及3个墙裂的建议...
  16. 笔记本计算机无线开关在哪里,笔记本电脑无线开关在哪怎么打开关闭
  17. android uikit框架详解,UIKit框架(2)框架简介
  18. 对Java实现单链表中.next的解释
  19. 打苹果,诉三星……陌生的它,是中国乃至全球最神秘科技公司
  20. 张益唐被曝已证明黎曼猜想相关问题,震动数学界

热门文章

  1. Winform DataGridView根据一列排序
  2. 如何编写一个智能家居app
  3. 高盛为什么强调自己是一家技术公司?
  4. 免费OA企业用户何去何从
  5. 微信公众平台接口开发基础
  6. Unity中的Shuriken粒子系统(3)
  7. Python基于Django的高校作业布置批改管理系统
  8. 基于SSM实现的游戏商城系统
  9. postgres启动服务器时missing or erroneous pg_hba.conf file
  10. Jasper创建柱状图(6.17.0)