嵌套 if 的请停典型用例:您希望对某些数据执行各种检查,以确保其有效,止使然后再最终对其进行有用的用嵌操作。
不要这样做!此方:
// JavaScriptfunction sendMoney(account,请停 amount) { if (account.balance > amount) { if (amount > 0) { if (account.sender === 'user-token') { account.balance -= amount; console.log('Transfer completed'); } else { console.log('Forbidden user'); } } else { console.log('Invalid transfer amount'); } } else { console.log('Insufficient funds'); }}
这里有一个更好的方法:
// JavaScriptfunction sendMoney(account, amount) { if (account.balance < amount) { console.log('Insufficient funds'); return; } if (amount <= 0) { console.log('Invalid transfer amount'); return; } if (account.sender !== 'user-token') { console.log('Forbidden user'); return; } account.balance -= amount; console.log('Transfer completed');}
看看它清洁了多少?我们没有嵌套 if,而是止使使用多个 if 语句来执行检查,如果条件不满足则立即返回。用嵌在这种模式中,此方我们可以将每个 if 语句称为保护子句。请停
如果您经常使用 Node.js,止使您可能在 Express 中间件中看到过以下流程:
// JavaScriptfunction authMiddleware(req,用嵌 res, next) { const authToken = req.headers.authorization; if (!authToken) { return res.status(401).json({ error: 'Unauthorized' }); } if (authToken !== 'secret-token') { return res.status(401).json({ error: 'Invalid token' }); } if (req.query.admin === 'true') { req.isAdmin = true; } next();}
这比前面好多了,对吧?:
// JavaScriptfunction authMiddleware(req, res, next) => { const authToken = req.headers.authorization; if (authToken) { if (authToken === 'secret-token') { if (req.query.admin === 'true') { req.isAdmin = true; } return next(); } else { return res.status(401).json({ error: 'Invalid token' }); } } else { return res.status(401).json({ error: 'Unauthorized' }); }};
你永远不会超出一层嵌套。我们可以避免回调地狱中出现的混乱情况。
如何将嵌套的 if 转换为保护子句
这样做的逻辑很简单:
这里我们可以清楚地看到它是 cond3 if。在此之后,如果我们不再进行任何检查并采取我们一直想要采取的行动。
// JavaScriptfunction func(cond1, cond2, cond3) { if (cond1) { if (cond2) { if (cond3) { console.log('PASSED!'); console.log('taking success action...'); } else { console.log('failed condition 3'); } } else { console.log('failed condition 2'); } } else { console.log('failed condition 1'); }}
否定 if 条件以将 else 语句的主体放在那里并在后面添加 return。
删除 else 大括号(保留正文,它仍然包含以前嵌套的 if,并将右 if 大括号移到 return 之后。
所以:
// JavaScriptfunction func(cond1, cond2, cond3) { if (!cond1) { // 👈 inverted if condition // 👇 body of former else clause console.log('failed condition 1'); return; // 👈 exit on fail } // 👇 remaining nested ifs to convert to guard clauses if (cond2) { if (cond3) { console.log('PASSED!'); console.log('taking success action...'); } else { console.log('failed condition 3'); } } else { console.log('failed condition 2'); }}
// JavaScriptfunction func(cond1, cond2, cond3) { if (!cond1) { console.log('failed condition 1'); return; } if (!cond2) { console.log('failed condition 2'); return; } // 👇 remaining nested ifs to convert if (cond3) { console.log('PASSED!'); console.log('taking success action...'); } else { console.log('failed condition 3'); }}
最后:
// JavaScriptfunction func(cond1, cond2, cond3) { if (!cond1) { console.log('failed condition 1'); return; } if (!cond2) { console.log('failed condition 2'); return; } if (!cond3) { console.log('failed condition 3'); return; } console.log('PASSED!'); console.log('taking success action...');}
提示:
安装 JavaScript Booster 扩展后,在 VS Code 中反转 if 语句很容易。
在这里,我们只需将光标放在 if 关键字上并激活“显示代码操作”命令(默认情况下为 Ctrl + .)
提示:
将保护子句拆分为多个函数以始终避免 else
如果我们在 if/else 中检查数据后想做其他事情怎么办?例如:
// JavaScriptfunction func(cond1, cond2) { if (cond1) { if (cond2) { console.log('PASSED!'); console.log('taking success action...'); } else { console.log('failed condition 2'); } console.log('after cond2 check'); } else { console.log('failed condition 1'); } console.log('after cond1 check');}
在此函数中,无论 cond1 的值如何,“after cond1 check”行仍将打印。如果 cond1 为 true,则 cond2 值也类似。
在这种情况下,使用保护子句需要做更多的工作:
如果我们尝试使用保护子句,我们最终会重复 if/else 检查之后的行:
function func(cond1, cond2) { if (!cond1) { console.log('failed condition 1'); console.log('after cond1 check'); return; } if (!cond2) { console.log('failed condition 2'); console.log('after cond2 check'); console.log('after cond1 check'); return; } console.log('PASSED!'); console.log('taking success action...'); console.log('after cond2 check'); console.log('after cond1 check');}func(true);
因为必须打印这些行,所以我们在返回之前在保护子句中打印它们。然后,我们在所有(!)以下保护子句中打印它。再次,在主函数体中,如果所有的保护子句都通过了。
那么我们能做些什么呢?我们怎样才能在使用保护子句的同时仍然坚持 DRY 原则呢?
好吧,我们将逻辑拆分为多个函数:
// JavaScriptfunction func(cond1, cond2) { checkCond1(cond1, cond2); console.log('after cond1 check');}function checkCond1(cond1, cond2) { if (!cond1) { console.log('failed condition 1'); return; } checkCond2(cond2); console.log('after cond2 check');}function checkCond2(cond2) { if (!cond2) { console.log('failed condition 2'); return; } console.log('PASSED!'); console.log('taking success action...');}
让我们将其应用到我们之前看到的 Express 中间件中:
// JavaScriptfunction authMiddleware(req, res, next) { checkAuthValidTokenAdmin(req, res, next);}function checkAuthValidTokenAdmin(req, res, next) { const authToken = req.headers.authorization; if (!authToken) { return res.status(401).json({ error: 'Unauthorized' }); } checkValidTokenAdmin(req, res, next);}function checkValidTokenAdmin(req, res, next) { const authToken = req.headers.authorization; if (authToken !== 'secret-token') { return res.status(401).json({ error: 'Invalid token' }); } checkAdmin(req, res, next);}function checkAdmin(req, res, next) { if (req.query.admin === 'true') { req.isAdmin = true; } next();}
在某种程度上,我们用责任链模式替换了 if/else 语句。
当然,对于像基本 Express 请求中间件这样的简单逻辑来说,这可能有点过分了,但这里的优点是它将每个额外的检查委托给一个单独的函数,分离职责并防止过度嵌套。
在代码中使用嵌套的 if 可能会导致代码复杂且难以维护。相反,我们可以使用保护子句来使我们的代码更具可读性和线性性。我们可以将保护子句应用于不同的场景,并将其拆分为多个功能,以避免重复和职责分割。通过采用这种模式,我们最终会编写出更干净、更易于维护的代码。
责任编辑:华轩 来源: web前端开发 嵌套 if开发(责任编辑:娱乐)
世界在建最宽独塔混合梁斜拉桥主塔基础工程完工 大桥全长1010米