前端教程——JavaScript函数中重构If/Else语句的方法
无论使用何种编程语言,代码都需要根据不同的情况对给定的输入做出不同的决定并执行相应的操作。举例来说,在游戏中,如果玩家的生命值是0,游戏就结束了。在气象应用程序中,如果观看早晨的日出,就会看到一张照片,如果是晚上,就会看到星月。本文中,我们将探究JavaScript中的条件语句是如何工作的。
如果您使用JavaScript,您将编写大量代码,其中包括条件调用。条件调用的基础可能很简单,但它所做的工作远不止是写一对if/else。下面是写出更好、更清晰的条件代码的一些技巧。
在本文中,我将介绍5种通过不必要的if-else语句来整理代码的方法。我将讨论默认参数,或(||)运算符,空位合并,可选链no-else-returns,和保护子句。
1、默认参数
你知道在使用不一致的API时会感到这种感觉,并且代码中断是因为某些值是undefined?
let sumFunctionThatMayBreak = (a, b, inconsistentParameter) => a+b+inconsistentParameter sumFunctionThatMayBreak(1,39,2) // => 42sumFunctionThatMayBreak(2,40, undefined) // => NaN123复制代码类型:[javascript]
对于许多人来说,解决该问题的本能方法是添加一条if/else语句:
let sumFunctionWithIf = (a, b, inconsistentParameter) => { if (inconsistentParameter === undefined){ return a+b } else { return a+b+inconsistentParameter } } sumFunctionWithIf(1,39,2) // => 42sumFunctionWithIf(2,40, undefined) // => 42123456789复制代码类型:[javascript]
但是,您可以简化上述功能,并if/else通过实现默认参数来消除逻辑:
let simplifiedSumFunction = (a, b, inconsistentParameter = 0) => a+b+inconsistentParametersimplifiedSumFunction(1, 39, 2) // => 42simplifiedSumFunction(2, 40, undefined) // => 42123复制代码类型:[java]
2、或运算符
上面的问题不能总是使用默认参数来解决。有时,你可能处在需要使用if-else逻辑的情况下,尤其是在尝试构建条件渲染功能时。在这种情况下,通常可以通过以下方式解决问题:
let sumFunctionWithIf = (a, b, inconsistentParameter) => { if (inconsistentParameter === undefined || inconsistentParameter === null || inconsistentParameter === false){ return a+b } else { return a+b+inconsistentParameter } } sumFunctionWithIf(1, 39, 2) // => 42sumFunctionWithIf(2, 40, undefined) // => 42sumFunctionWithIf(2, 40, null) // => 42sumFunctionWithIf(2, 40, false) // => 42sumFunctionWithIf(2, 40, 0) // => 42/// 🚨🚨🚨 but:sumFunctionWithIf(1, 39, '') // => "40"123456789101112131415复制代码类型:[javascript]
或这样:
let sumFunctionWithTernary = (a, b, inconsistentParameter) => { inconsistentParameter = !!inconsistentParameter ? inconsistentParameter : 0 return a+b+inconsistentParameter } sumFunctionWithTernary(1,39,2) // => 42sumFunctionWithTernary(2, 40, undefined) // => 42sumFunctionWithTernary(2, 40, null) // => 42sumFunctionWithTernary(2, 40, false) // => 42sumFunctionWithTernary(1, 39, '') // => 42sumFunctionWithTernary(2, 40, 0) // => 4212345678910复制代码类型:[javascript]
但是,你可以使用或(||)运算符进一步简化它。||运算符的工作方式如下:
当左侧为假值时,它将返回右侧。
如果为真值,它将返回左侧。
然后,解决方案可能如下所示:
let sumFunctionWithOr = (a, b, inconsistentParameter) => { inconsistentParameter = inconsistentParameter || 0 return a+b+inconsistentParameter } sumFunctionWithOr(1,39,2) // => 42sumFunctionWithOr(2,40, undefined) // => 42sumFunctionWithOr(2,40, null) // => 42sumFunctionWithOr(2,40, false) // => 42sumFunctionWithOr(2,40, '') // => 42sumFunctionWithOr(2, 40, 0) // => 4212345678910复制代码类型:[javascript]
3、空位合并
但是,有时候,你确实想保留0或''作为有效参数,而不能使用||来做到这一点。运算符(如上例所示)。幸运的是,从今年开始,JavaScript使我们可以访问??。(空位合并)运算符,仅当左侧为null或未定义时才返回右侧。这意味着,如果你的参数为0或'',它将被视为此类。让我们看一下实际情况:
let sumFunctionWithNullish = (a, b, inconsistentParameter) => { inconsistentParameter = inconsistentParameter ?? 0.424242 return a+b+inconsistentParameter } sumFunctionWithNullish(2, 40, undefined) // => 42.424242sumFunctionWithNullish(2, 40, null) // => 42.424242/// 🚨🚨🚨 but:sumFunctionWithNullish(1, 39, 2) // => 42sumFunctionWithNullish(2, 40, false) // => 42sumFunctionWithNullish(2, 40, '') // => "42"sumFunctionWithNullish(2, 40, 0) // => 421234567891011复制代码类型:[javascript]
4、可选链接
最后,当处理不一致的数据结构时,很难相信每个对象将具有相同的密钥。看这里:
let functionThatBreaks = (object) => { return object.name.firstName } functionThatBreaks({name: {firstName: "Sylwia", lasName: "Vargas"}, id:1}) // ✅ "Sylwia" functionThatBreaks({id:2}) // 🚨 Uncaught TypeError: Cannot read property 'firstName' of undefined 🚨123456复制代码类型:[javascript]
发生这种情况是因为object.name是undefined,因此我们无法对其进行调用firstName。
许多人通过以下方式处理这种情况:
let functionWithIf = (object) => { if (object && object.name && object.name.firstName) { return object.name.firstName } } functionWithIf({name: {firstName: "Sylwia", lasName: "Vargas"}, id:1) // "Sylwia" functionWithIf({name: {lasName: "Vargas"}, id:2}) // undefined functionWithIf({id:3}) // undefined functionWithIf() // undefined123456789复制代码类型:[javascript]
但是,您可以使用新的JS功能(可选链接)简化上述操作。可选链在每一步都会检查返回值是否为undefined,如果是,它将仅返回该值而不抛出错误:
let functionWithChaining = (object) => object?.name?.firstName functionWithChaining({name: {firstName: "Sylwia", lasName: "Vargas"}, id:1}) // "Sylwia" functionWithChaining({name: {lasName: "Vargas"}, id:2}) // undefined functionWithChaining({id:3}) // undefined functionWithChaining() // undefined12345复制代码类型:[javascript]
5、no-else-return和警告条款
笨拙的if/else语句(尤其是那些嵌套语句)的最后解决方案是no-else-return语句和guard子句。因此,假设我们具有以下功能:
let nestedIfElseHell = (str) => { if (typeof str == "string"){ if (str.length > 1) { return str.slice(0,-1) } else { return null } } else { return null } } nestedIfElseHell("") // => null nestedIfElseHell("h") // => nullnestedIfElseHell("hello!") // => "hello"1234567891011121314复制代码类型:[javascript]
no-else-return
现在,我们可以使用以下no-else-return语句简化此函数,因为无论如何我们返回的都是null:
let noElseReturns = (str) => { if (typeof str == "string"){ if (str.length > 1) { return str.slice(0,-1) } } return null } noElseReturns("") // => null noElseReturns("h") // => nullnoElseReturns("hello!") // => "hello"1234567891011复制代码类型:[javascript]
该no-else-return语句的好处是,如果不满足条件,该函数将结束的执行if-else并跳至下一行。你甚至可以不使用最后一行(returnnull),然后返回undefined。
注意:我实际上在前面的示例中使用了一个no-else-return函数。
警告条款
现在,我们可以更进一步,并设置防护措施,甚至可以更早地结束代码执行:
let guardClauseFun = (str) => { // ✅ first guard: check the type if (typeof str !== "string") return null // ✅ second guard: check for the length if (str.length <= 3) console.warn("your string should be at least 3 characters long and its length is", str.length) // otherwise: return str.slice(0,-1) } guardClauseFun(5) // => null guardClauseFun("h") // => undefined with a warningguardClauseFun("hello!") // => "hello"