当然,它们是创建控制流的一种简单方式,但你可以写数十亿行条件 JS 代码而不使用一个 if 语句。
在许多情况下,使用不同的结构可以更清晰地表达你想做的事 — 只要我们还在为人类编写代码,这就是我们不能忽视的。
更不用说更低的冗长度和更短的代码了...
所以:让我们看看一些强大的 if 语句升级📈。
1. AND (&&) 运算符
JavaScript 独有的 && 运算符。
使用它,我可以快速地从这个:
function visitSite(user) {
if (user.isLoggedIn) {
console.log(`你是 ${user.name}`);
}
console.log('欢迎来到 Coding Beauty。');
}
变成这个:
function visitSite(user) {
user.isLoggedIn && console.log(`你是 ${user.name}`);
console.log('欢迎来到 Coding Beauty。');
}
我消除了嵌套并将分支逻辑压缩成了一行。
你想在有 if
但没有对应的 else
时使用这个;特别是当 if
块只有一行时。
即使有多行,你也可以将它们抽象到一个单独的函数中,然后再次应用 &&
。毕竟,我们例子中的 console.log()
本身就是一个抽象。
所以这个:
function visitSite(user) {
if (user.isLoggedIn) {
console.log(`欢迎回来, ${user.name}!`);
console.log(`你上次登录是在 ${user.lastLoginDate}`);
console.log(`你的账户类型是 ${user.accountType}`);
}
console.log('欢迎来到 Coding Beauty。');
}
转变为这个:
function visitSite(user) {
user.loggedIn && handleUser(user);
console.log('欢迎来到 Coding Beauty。');
}
function handleUser(user) {
console.log(`欢迎回来, ${user.name}!`);
console.log(`你上次登录是在 ${user.lastLoginDate}`);
console.log(`你的账户类型是 ${user.accountType}`);
}
2. 三元运算符
三元运算符让我们可以将 if-else
语句压缩成一行。
当所有条件情况只涉及为同一个变量赋值时,它们是 if-else
的绝佳替代品。
这里有一个例子:
let word;
if (num === 7) {
word = '七';
} else {
word = '未知';
}
尽管 DRY 原则不是硬性规定,但在这种情况下,如果我们使用三元运算符来避免两次写变量赋值,事情会变得更加清晰:
const word = num === 7 ? '七' : '未知';
现在我们甚至可以使用 const 来保持不可变性和纯粹性。
嵌套的三元运算符
当我们在 if-else 语句中有 3 个或更多分支,或者我们嵌套 if 时,更清晰的三元替代方案将包含内部三元运算符。
所以这个:
const getNumWord = (num) => {
if (num === 1) {
return '一';
} else if (num === 2) {
return '二';
} else if (num === 3) {
return '三';
} else if (num === 4) {
return '四';
} else {
return '未知';
}
};
变成:
const getNumWord = (num) =>
num === 1
? '一'
: num === 2
? '二'
: num === 3
? '三'
: num === 4
? '四'
: '未知';
不过有些人确实会抱怨嵌套的三元运算符,认为它们复杂且晦涩。但我认为这更多是个人偏好问题,或者可能是格式化不佳。
说到格式化,我们有像 Prettier 这样的工具已经做这项工作(而且只做这项工作)几个世纪了:
只要有足够的缩进,你应该不会有可读性问题。如果分支比上面的更复杂,你可能想把一些低层逻辑移到前面的变量或小函数中。
说到可读性,Prettier 正在改变他们的嵌套三元风格;他们想出了一种相当独特的方式。
当前的风格巧妙地结合了扁平和树状嵌套;为真值分支中的嵌套三元添加了进一步的缩进,但保持假值分支的扁平。
const 动物名称 = 宠物.会吱吱叫()
? '老鼠'
: 宠物.会吠叫()
? 宠物.是否可怕()
? '狼' // 只有在逻辑为真时才会嵌套
: '狗'
: 宠物.会喵喵叫()
? '猫'
: 宠物.会吱吱叫() // 逻辑为假时会返回平铺结构
? '老鼠'
: '可能是一只兔子';
但很快 Prettier 将把上面的格式化成这样:
const 动物名称 =
宠物.会吱吱叫() ? '老鼠'
: 宠物.会吠叫() ? (宠物.是否可怕() ? '狼' : '狗')
: 宠物.会喵喵叫() ? '猫'
: 宠物.会吱吱叫() ? '老鼠'
: '可能是一只兔子';
主要的变化是所有的 ? 现在都在其结束的同一行的末尾,而不是下一行。
3. Switch 语句
你会在 C 风格的语言如 Java、C#和 Dart 中找到这个 — 它在这些语言中看起来完全一样,只有一些语义上的差异。
如果三元运算符最适合为一个变量生成输出,那么 switch 语句最适合处理来自一个变量的输入:
function processUserAction(action) {
switch (action) {
case 'play': // 如果 (action === 'play')
console.log('Playing the game...');
startGame({ mode: 'multiplayer' });
break;
case 'pause': // 否则如果 (action === 'pause')
console.log('Pausing the game...');
pauseGame();
break;
case 'stop':
console.log('Stopping the game...');
endGame();
goToMainMenu();
break;
case 'cheat':
console.log('Activating cheat mode...');
enableCheatMode();
break;
default: // 否则
console.log('Invalid action!');
break;
}
}
switch 语句的独特力量来自于能够省略每个 case 结尾的 break,让执行"落透"到下一个 case:
// 生成一个 1 到 6 的随机数来模拟掷骰子
const diceRoll = Math.floor(Math.random() * 6) + 1;
console.log(`You rolled a ${diceRoll}!`);
switch (diceRoll) {
case 1:
console.log('Oops, you rolled a one!');
console.log('You lose a turn.');
break;
case 2:
console.log('Two heads are better than one... sometimes');
break;
case 4:
case 6:
// 如果 (diceRoll === 2 || diceRoll === 4 || diceRoll === 6)
console.log('Nice roll!');
console.log('You move forward two spaces.');
break;
// ...
default:
console.log('Invalid dice roll.');
}
大多数其他有 switch-case 的语言都允许这样做,值得注意的例外是 C#。
4. 键值对象
键值对象让我们可以声明式地将输入映射到输出。
const weatherActivities = {
sunny: 'go to the beach', // 晴天:去海滩
rainy: 'watch a movie at home', // 雨天:在家看电影
cloudy: 'take a walk in the park', // 阴天:去公园散步
snowy: 'build a snowman', // 雪天:堆雪人
};
const weather = 'sunny';
console.log(`Okay, so right now it's ${weather}.`); // 好的,现在是晴天。
console.log(`Why don't you ${weatherActivities[weather]}?`); // 你为什么不去海滩呢?
当我在 React Native 应用中创建屏幕时,这对我来说真的很棒 — 每个屏幕都有自己的加载、错误和成功状态。
这里是我们应用中一个屏幕的片段:
// screens/course-list.tsx
// …
import {
ActivityIndicator,
Text
// …
} from 'react-native-paper';
type ViewState = 'loading' | 'error' | 'data';
export function Courses({ route, navigation }) {
const [viewState, setViewState] = useState<ViewState>('loading');
const state = useAppState();
const courses = state?.courseList;
// …
const contentDict = {
loading: <ActivityIndicator />,
error: <Text>Error</Text>,
data: <CourseList courses={courses} />,
};
const content = contentDict[viewState];
return (
<View>
<StatusBar />
{content}
</View>
);
}
// …
最后的思考
所以 if 语句一点也不坏,它们非常适合以容易理解的方式编写条件逻辑。
但重要的是要考虑替代方法,使代码更短、更清晰,甚至更具表现力。这不是要完全消除 if 语句,而是采用有效的技术,使我们的代码更高效、更优雅。
首发于公众号 大迁世界,欢迎关注。📝 每周一篇实用的前端文章 🛠️ 分享值得关注的开发工具 ❓ 有疑问?我来回答
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。