原文连接: 9 Tricks for Kickass JavaScript Developers in 2019
github 的地址 欢迎 star!
固然做者是在今年1月份写的!我感受大部分功能都已经使用好久啦,你们看看就好啦,就当总结回顾javascript
又一年过去了,JavaScript 也一直在变化进步着。这儿列举了一些小技巧帮你在 2019 年写出更简洁,高效的可拓展的代码。下面共列举了 9 个讲究使用的小技巧来帮助你成为更好的开发者。css
若是你还陷入到回调地狱中,那么你应该回到 2014 年去开发你的代码。除非绝对必要(像第三方库须要或者性能缘由),不然不要使用回调。Promise 是很是好的解决回调地狱,可是当你的代码变得愈来愈大时,它也会变得不太好用。我如今的解决方案就是 async / await
,它极大提升了代码可读性以及简洁性。在全部使用Promise的地方你均可以替换成 await,在你须要返回 Promise 对象,简单 await
它并返回,为了使它不报错,你须要在定义函数的开头添加 async
。事实上,async / await
就是 Promise 的语法糖。下面就是一个简单的例子:html
async function getData() {
const result = await axios.get('https://dube.io/service/ping')
const data = result.data
console.log('data', data)
return data
}
getData()
// 对于在外部要使用getData中数据的话,是要 await getData()取到data的,async老是返回一个Promise对象
复制代码
await 操做符用于等待一个 Promise 对象。它只能在异步函数 async function 中使用。
async / await
是属于 ES2017 的内容,因此可能须要 babel 编译你的代码。不过如今的主流浏览器都已经支持了。前端
另外推荐 justjavac 大神翻译的 await、return 和 return await 的陷阱以及这篇翻译 javascript-async-await-the-good-part-pitfalls-and-how-to-use 能够更加详细的理解相关知识。java
常常地,咱们会遇到这样的需求,请求获取多个数据集并对每一个数据集进行各自处理或者须要等全部异步回调完成后返回一个值。遇到这些状况,我是这么处理的:react
for…of
假设咱们的页面有多个 Pokemon(口袋妖怪),须要获取到它们的详细的信息。咱们不想等全部调用结束,特别是不知道它有多少次调用,咱们仅想在它有调用返回时就更新咱们的数据集。能够用 for…of
来遍历数组,在代码块里执行 async
,这样的话,只有每次 await
执行成功,代码才会继续往下执行。 这里要着重说明,这样作可能会致使性能瓶颈(当请求不少的时候),但像这样作才能到达预期的效果。请看下面的例子:webpack
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.data
updateData(newData)
console.log(myData)
}
}
function updateData(newData) {
myData = myData.map(el => {
if(el.id === newData.id) return newData
return el
})
}
fetchData(myData)
复制代码
这个代码是能正常运行,你能够轻松地复制它到 code sandbox 运行。ios
若是你想同时获取全部口袋妖怪的详情呢?你须要等待全部的请求的完成返回,这时简单使用 Promise.all
:git
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 newData
return el
})
}
fetchData(myData)
复制代码
for...of 和 Promise.all
都是 ES6 之后提出来的,请确保你的环境能运行。github
咱们接着上面的那个例子,提取一部分代码:
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 + val
case 'subtraction':
return acc - val
case 'multiplication':
return acc * val
case '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
复制代码
这个例子起初看起来可能有点混乱,可是慢慢观察。当咱们没有给函数传递参数的时候,就会使用默认值。一旦咱们开始传递参数,仅会使用那些没有传递的参数的默认值。这样,减小了你对异常状态的处理。
当使用默认值,就能够不用对现有值进行一些额外的检查。可是了解你的变量是真值仍是假值是很是棒的。它能提升你的代码扩展性,更具备说服力的以及简洁。我常看到下面一些写法:
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(...)
}
<!-- 固然做者这里的类比可能有必定问题,0!= NaN ,!myNumber是把范围都扩大了,若是需求是只要判断是否NaN,仍是应该要用isNaN的方法-->
复制代码
为了用这些简洁的判断,你要充分理解js中真值,假值具体有哪些?这里概述一下:
逻辑运算是基于多个表达式真假的判断,注意到js是惰性求值的策略。逻辑运算通常返回一个布尔值。&& 和 || 运算符会返回一个指定操做数的值。来看这里:
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
复制代码
进行的逻辑运算,是按照下面的规则进行的:
&&
:第一个值为假值,则直接返回;若是为真值,则直接返回第二的值
||
:第一个值为真,则直接返回;若是为假,则直接返回第二的值。
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
复制代码
三元运算符和逻辑运算是类似的,可是它有3个部分: condition ? expr1 : expr2
例如:
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 evening
复制代码
过去在 Object 属性链的调用中,很容易由于某个属性不存在而致使以后出现 Cannot read property xxx of undefined 的错误。为了确认须要向这样处理:
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
复制代码
我认为它是检查嵌套属性最佳方法,代码是如此的简洁。
这个特性能够说是很是实用了,不过它如今处于 stage-1 阶段。你能够在
.babelrc
文件中引入 @babel/plugin-proposal-optional-chaining插件来使用它。
在 JavaScript 中函数绑定也是常常的工做任务。如今,你们应该都是用箭头函数自动绑定 this 到这个类上的(这里可能有歧义,首先箭头函数里面是没有 this 和 arguments 的,这里的 this 把它当成一个参数就行)。若是不用箭头函数,咱们就须要在构造函数绑定 this,当类的方法不少的时候,这就显得很冗余。所以,建议和提倡在类里面用箭头函数。如:
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 })
}
}
复制代码
关于必须 bind 传参的状况能够看看个人另一篇文章
使用箭头函数声明类中方法,它如今处于 stage-3 阶段。你能够在.babelrc
文件中引入@babel/plugin-proposal-class-properties插件来使用它。
做为一个前端,你也确定会遇到打包和编译代码状况。彷佛 webpack 成为标准已经很长时间了。我从 webpack 1 版本就开始使用它了,固然那是痛苦的。为了弄懂它全部的配置项,我花了无数的时间才让它正常打包和编译。若是还有选择的机会,我是不会学习webpack的。恰巧几个月前用了 parcel,历来没有发现配置能够如此简单!你不须要改动什么便能获得你预期的效果,固然你也能够修改配置项。它也是和 webpack 或 babel 同样是可配置的,同时也是快速的。若是你不知道 parcel,我明确建议你去学习它!
固然,如今的主流标准仍是 webpack,webpack 4 以后配置也简洁了,能够在学习 parcel 以后了解 webpack,不说了,又要开始学习 webpack 5
谈到这个话题,我有不少想要分享讨论的东西。对于css,许多人更倾向于使用第三方组件库像 bootstrap。对于 JavaScript,我也看到不少人喜欢用 jQuery 以及一些小型的验证,滚动的库等等。虽然使用库是方便的,可是我强烈建议你能本身实现它,而不是盲目的安装 npm 包。当它变成一个很大的库或者框架的时候,整个团队都要构建它,像 moment.js或者 react-datepicker,并且当需求发生改变时,你想要改动它是困难的。因此,你应该写更多本身的组件。这将会带来三个重要的优势:
在开始,使用 npm 包是方便的。你能花更多时间去实现本身的业务逻辑。但当那个包没有按照预期运行时,你又换了一个包,这时不得不花更多时间去读它的 API 才能使用它。当是你本身实现的库(组件)时,你能百分百用本身的用例来定制化开发它。
我很是赞同这个的评论:不少人被'不要重复造轮子'的格言所困扰,由于他们把它理解成'不要重复实现轮子',对于一个热爱编程的人,老是要有好奇心和不断钻研的,但愿你们和我同样谨记!
实现本身的轮子是多么有成就感的一件事情! 后续我也会把本身的轮子放在github上。
文中提到的点其实都是基础,但实用的。对于新手 JavaScript 开发者,其实我更建议应该开始学习 TypeScript 了。由于它实在太好了!这里给出了本身学习 TypeScript 一些历程
若是有错误或者不严谨的地方,请务必给予指正,十分感谢!