2019年JavaScript开发人员的9个小技巧
又过了一年,JavaScript不断变化。但是,有一些提示可以帮助您编写可扩展的干净,高效的代码,下面列出了9个实用技巧,这些技巧将使您成为更好的开发人员。
放在最前面,文章很长,技术点很多,希望不会影响你的观看(非诚勿扰):
自己整理了一份最全面前端学习资料,从最基础的HTML+CSS+JS [炫酷特效,游戏,插件封装,设计模式]到移动端HTML5的项目实战的学习资料都有整理,送给每一位前端小伙伴, 有想学习web前端的,或是转行,或是大学生,还有工作中想提升自己能力的,正在学习的小伙伴欢迎加入学习。
加Q 裙:777093078(招募中)
1. async / await
你可以在JavaScript中await每一个Promise,事实上,async/await只是promises的语法糖。要使代码正常工作,只需在函数前添加async关键字即可。下面是一个简单的例子:
async function getData() {
const result = await axios.get('https://dube.io/service/ping')
const data = result.data
console.log('data', data)
return data
}
getData()
ES2017引入了async/await,因此请务必转换代码。
2. async control flow
通常,在所有异步调用返回值之后,有必要获取多个数据集并为每个数据集执行某些操作或完成任务。
for…of
假设我们的页面上有几个Pokemon,我们必须获取有关它们的详细信息。我们不想等待所有调用完成,特别是当我们不知道有多少调用时,但是我们想要在得到回报后立即更新我们的数据集。我们可以使用for...of循环遍历数组并在块内执行async代码,执行将暂停,直到每次调用都成功。
重要的是要注意,如果在代码中执行此类操作可能会出现性能瓶颈,但保留在工具集中非常有用。这是一个例子:
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)
Promise.all
如果你想并行获取所有的Pokemon怎么办?由于您可以await所有Promises,只需使用Promise.all即可
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+引入的,所以一定要转换你的代码。
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 + 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
这个例子起初可能看起来有点令人困惑,但要花时间玩弄它。当我们没有将任何值作为参数传递给我们的函数时,使用默认值。一旦我们开始传递值,就只使用不存在的参数的默认值。
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(...)
}
要真正利用这些陈述,您必须了解真实和虚假的价值。这是一个小概述:
Falsy
strings with the length of 0
the number 0
false
undefined
null
NaN
Truthy
empty arrays
empty objects
Everything else
请注意,在检查truthy/falsy值时,没有明确的比较,这相当于检查双等号==而不是三个===。一般来说,它的行为方式相同,但在某些情况下,您最终会遇到错误。对我来说,它主要发生在数字0。
5. 逻辑和三元运算符
这些用于缩短代码,节省宝贵的代码行。通常它们都是很好的工具,有助于保持代码清洁,但它们也会产生一些混乱,特别是在链接它们时。
逻辑运算符
逻辑运算符基本上组合了两个表达式,将返回true,false或匹配值
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
我们可以将逻辑运算符与我们从最后一点,真实和虚假值的知识结合起来。使用逻辑运算符时,以下规则适用:
&& : 返回第一个falsy值,如果没有,则返回最后一个truthy值。
|| :返回第一个truthy值,如果没有,则操作将等于最后一个falsy值。
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
三元运算符
三元运算符与逻辑运算符非常相似,但有三个部分:
比较,要么是假的,要么是真实的
第一个返回值,如果比较是真实的
第二个返回值,如果比较是假的
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
6. 可选链接
您是否遇到过访问嵌套对象属性的问题,而不知道对象或其中一个子属性是否存在?你可能会得到这样的东西:
let data
if(myObj && myObj.firstProp && myObj.firstProp.secondProp && myObj.firstProp.secondProp.actualData) data = myObj.firstProp.secondProp.actualData
这是乏味的,并且有一种更好的方法,至少是一种提议的方式(继续阅读如何启用它)。它被称为可选链接,其工作原理如下:
const data = myObj?.firstProp?.secondProp?.actualData
这是一种检查嵌套属性并使代码更清晰的方式。
目前,可选链接不是官方规范的一部分,但作为实验性功能处于第一阶段。
7. 类属性和绑定
JavaScript中的绑定功能是一项常见任务。通过在ES6规范中引入箭头函数,我们现在有了一种自动将函数绑定到声明上下文的方法 - 在JavaScript开发人员中非常有用且常用,首次引入类时,您不能再使用箭头函数,因为必须以特定方式声明类方法。我们需要在其他地方绑定函数,例如在构造函数中(使用React.js的最佳实践)。我总是被首先定义类方法然后绑定它们的工作流程所困扰,一段时间后它似乎很荒谬。使用类属性语法,我们可以再次使用箭头函数并获得自动绑定的优点。现在可以在类中使用箭头函数。以下是绑定_increaseCount的示例:
class Counter extends React.Component {
constructor(props) {
super(props)
this.state = { count: 0 }
}
render() {
return(
{this.state.count}
Increase Count
)
}
_increaseCount = () => {
this.setState({ count: this.state.count + 1 })
}
}
目前,类属性不是官方规范的一部分,但是作为实验特征处于第3阶段。
8. Use parcel
作为前端开发人员,您几乎肯定遇到过捆绑和转换代码。parcel (https://parceljs.org/),它可以为您提供开箱即用的功能,同时还可以根据需要更改它。它还支持一个插件系统,类似于webpack或babel,速度非常快。
9. 自己写更多代码
这是一个很好的主题。关于它,我有很多不同的讨论。即使对于CSS,很多人也倾向于使用像bootstrap这样的组件库。对于JavaScript,仍然看到人们使用jQuery和小型库进行验证,滑块等。虽然使用库是有意义的,但我强烈建议您自己编写更多代码,而不是盲目地安装npm软件包。当有大型库(甚至是框架),整个团队正在构建它时,例如moment.js或react-datepicker,尝试自己编写它是没有意义的。但是,您可以自己编写大部分代码。这将为您提供三个主要优势:
1. 您确切知道代码中发生了什么
2. 在某些时候,您将开始真正理解编程以及工作原理
3. 您可以防止代码库变得臃肿