JavaScript一直在变化和改进,这里有一些技巧可帮助您在2019年编写更简洁、高效和可扩展的代码。这里有9个实用技巧可帮助您成为更好的开发人员.1.async/await如果你还陷在回调地狱,那么你应该回到2014年去开发你的代码。除非绝对必要(例如第三方库要求或出于性能原因),否则不要使用回调。Promises是回调地狱的一个很好的解决方案,但随着您的代码变得越来越大,它们也会变得不那么有用。我目前的方案是async/await,大大提高了代码的可读性和简洁性。凡是用到Promise的地方,都可以换成await。当你需要返回一个Promise对象时,只需等待它并返回它。为了让它不报错,需要在定义函数的开头加上async。实际上,async/await就是Promise的语法糖。下面是一个简单的例子:asyncfunctiongetData(){constresult=awaitaxios.get('https://dube.io/service/ping')constdata=result.dataconsole.log('data',data)returndata}getData()的await运算符用于等待Promise对象。它只能在异步函数内部使用。async/await是属于ES2017的东西,所以可能需要babel来编译你的代码。现在所有主流浏览器都支持它。2.异步控制流程我们经常会遇到请求多个数据集并分别处理每个数据集,或者所有异步回调完成后返回一个值的需求。在这些情况下,我是这样处理的:for...of假设我们的页面有多个神奇宝贝(Pokemon),我们需要获取它们的详细信息。我们不想等待所有调用完成,尤其是不知道它被调用了多少次,我们只想在其中一个调用返回时更新我们的数据集。您可以使用for...of遍历数组并在代码块中执行异步。这样,只有每次await执行成功,代码才会继续执行。这里需要注意的是,这样做可能会造成性能瓶颈(当请求很多的时候),但是只有这样做才能达到预期的效果。请看下面的例子:importaxiosfrom'axios'letmyData=[{id:0},{id:1},{id:2},{id:3}]asyncfunctionfetchData(dataSet){for(entryofdataSet){constresult=awaitaxios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)constnewData=result.dataupdateData(newData)console.log(myData)}}functionupdateData(newData){myData=myData.map(el=>{if(el.id===newData.id)returnnewDatareturnel})}fetchData(myData)这段代码运行正常,你可以很方便的将它复制到代码沙箱中运行。Promise.all如果想同时获取所有宝可梦的详情?您需要等待所有请求完成并返回,然后只需使用Promise.all:importaxiosfrom'axios'letmyData=[{id:0},{id:1},{id:2},{id:3}]asyncfunctionfetchData(dataSet){constpokemonPromises=dataSet.map(entry=>{returnaxios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)})constresults=awaitPromise.all(pokemonPromises)results.forEach(result=>{updateData(result.data)})console.log(myData)}functionupdateData(newData){myData=myData.map(el=>{if(el.id===newData.id)returnnewDatareturnel})}fetchData(myData)for...of和Promise.all都是在ES6之后提出的,请确保你的环境可以运行。3.解构(Destructuring)&默认值我们照着上面的例子,提取部分代码:constresult=axios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)constdata=result.data有一种简单的方法来解构以从数组或对象中获取一些属性(值)。像这样:const{data}=awaitaxios.get(...)注意,在解构的时候,通常会被赋予一个默认值。这确保您不会得到undefined并且您不必自己手动检查变量。const{id=5}={}console.log(id)//5这个技巧同样适用于函数参数。例如:functioncalculate({operands=[1,2],type='addition'}={}){returnoperands.reduce((acc,val)=>{switch(type){case'addition':returnacc+valcase'减法':returnacc-valcase'乘法':returnacc*valcase'除法':returnacc/val}},['加法','减法'].includes(type)?0:1)}console.log(calculate())//3console.log(calculate({type:'division'}))//0.5console.log(calculate({operands:[2,3,4],type:'multiplication'}))//24这些示例起初可能看起来有点混乱,但慢慢来。当我们不向函数传递参数时,将使用默认值。一旦我们开始传递参数,只会使用那些没有传递的默认值。通过这种方式,您可以减少对异常状态的处理。4.True&False当使用默认值时,可以避免一些对已有值的额外检查。但是知道你的变量是真还是假是非常棒的。它可以提高你的代码的可扩展性,更有说服力和简洁。经常看到这样的写法:if(myBool===true){console.log(...)}//ORif(myString.length>0){console.log(...)}//ORif(isNaN(myNumber)){console.log(...)}为了使用这些简洁的判断,你需要充分理解js中的真值,具体的假值是什么?概览如下:false值:1.String,但Length为02.Number03.false4.undefined5.null6.NaNTrue值:1.空数组2.空对象3.其他有值的数据。注意:在判断真假值时,还应注意使用等于'==',或全等'===',这通常会导致错误。对我来说,它通常是数字0。逻辑运算和三元运算符逻辑运算逻辑运算是基于对多个表达式的真假判断。注意js是惰性求值策略。逻辑运算一般返回一个布尔值。&&和||运算符返回指定操作数的值。看这里:console.log(true&&true)//trueconsole.log(false&&true)//falseconsole.log(true&&false)//falseconsole.log(false&&false)//falseconsole.log(true||true)//trueconsole.log(true||false)//trueconsole.log(false||true)//trueconsole.log(false||false)//false按照以下规则进行逻辑运算:&&:第一个值如果是false值,它会直接返回;如果是真值,则直接返回第二个值||:第一个值为真,则直接返回;如果为false,则直接返回第二个值。console.log(0&&{a:1})//0console.log(false&&'a')//falseconsole.log('2'&&5)//5console.log([]||false)//[]console.log(NaN||null)//nullconsole.log(true||'a')//true三元运算符三元运算符类似于逻辑运算,但它有3个部分:条件?expr1:expr2condition是条件判断的部分,会得到真或假的值。expr1是判断条件为真时返回的值。expr2是判断条件为假时返回的值。例如:constlang='German'console.log(lang==='German'?'Hallo':'Hello')//Halloconsole.log(lang?'Ja':'Yes')//Jaconsole.log(lang==='French'?'Bonsoir':'Goodevening')//Goodevening6.OptionalChaining以前在Object属性链的调用中,很容易因为某个属性不存在而导致Cannotreadpropertyxxxofundefined的错误。为了确认需要这样处理:letdataif(myObj&&myObj.firstProp&&myObj.firstProp.secondProp&&myObj.firstProp.secondProp.actualData)data=myObj.firstProp.secondProp.actualData这是多余的。有一个新的提议方法叫做OptionalChaining,如下形式:constdata=myObj?.firstProp?.secondProp?.actualData我认为这是检查嵌套属性的最好方法,代码如此简洁。这个特性可以说是非常好用,但是目前处于stage-1阶段。你可以通过在你的.babelrc文件中包含@babel/plugin-proposal-optional-chaining插件来使用它。7.类属性和绑定JavaScript中的函数绑定也是一个常见的任务。现在,大家应该是用箭头函数把this自动绑定到这个类上了(这里可能有歧义,首先箭头函数里面没有this和arguments,这里的this可以看成是参数)。如果我们不使用箭头函数,我们需要在构造函数中绑定this。当类中有很多方法时,这是非常多余的。因此,推荐和提倡在类中使用箭头函数。如:classCounterextendsReact.Component{constructor(props){super(props)this.state={count:0}}render(){return(
