在编写 js 的过程中,我们肯定会用到条件语句。
常用的 if...else
大部分的条件语句都是用 if...else,适用于“非黑即白”的情况:
场景一:是否登录
根据不同的登录态做不同的行为:
if (isLogin) {
// do something} else {
this.login()
}
场景二:性别差异
根据不同的性别做不同的行为:
if (sex === 'male') {
// do something} else {
// do something}
判断条件变多时
也有一些时候条件的情况可能超过两种,这个时候可以用 if...else if...else:
场景一:成绩等级差异
根据不同的等级做不同的行为:
if (grade === 'A') {
// do something} else if (grade === 'B') {
// do something} else {
// do something}
当然,还会有某些情况下,条件可能会更多,这个时候就有很多种选择方案了:
场景二:一周的日期
根据不同的日期吃不同的食物:
function eat(food) {
console.log('eat food:', food)
}
function getFood(day) {
if (day === 'day0') {
eat('apple')
} else if (day === 'day1') {
eat('banana')
} else if (day === 'day2') {
eat('orange')
} else if (day === 'day3') {
eat('noodle')
} else if (day === 'day4') {
eat('milk')
} else if (day === 'day5') {
eat('rice')
} else if (day === 'day6') {
eat('water')
}
}
(插一句,我们可以尽可能把出现概率高的放在前面,这样可以提高效率。)
这种情况下有七个判断条件,可以看到可能有一点乱,这个时候,就可以考虑用 switch 语句了,这是针对较多条件下的判断方式:
function eat(food) {
console.log('eat food:', food)
}
function getFood(day) {
switch (day) {
case 'day0':
eat('apple')
break;
case 'day1':
eat('banana')
break;
case 'day2':
eat('orange')
break;
case 'day3':
eat('noodle')
break;
case 'day4':
eat('milk')
break;
case 'day5':
eat('rice')
break;
default:
eat('water')
}
}
可以看到,虽然代码行数多了一点,但是更加简洁易懂。 另:关于 switch,有几个注意点。switch 里的条件和 case 的条件要 ===,不然不会匹配
每个 case 都要记得加上 break
可以利用 switch (true) 来解决一些条件判断:
switch (true) {
case age > 0 && age < 20:
// do something break;
// ...}
一般讲到这里基本就结束了,不过后来看到了一篇文章,感觉很赞,学习了一下。 比如我们可以把上面的“一周的日期”这个场景重写一下:
function eat(food) {
console.log('eat food:', food)
}
const foodObj = {
'day0': 'apple',
'day1': 'banana',
'day2': 'orange',
'day3': 'noodle',
'day4': 'milk',
'day5': 'rice',
'day6': 'water'
}
function eatFood(day) {
eat(foodObj[day])
}
可以发现,代码量是不是少了很多。将条件变成对象键值对。 当然,可以用对象就可以用 map 结构:
function eat(food) {
console.log('eat food:', food)
}
const foodMap = new Map([
['day0', 'apple'],
['day1', 'banana'],
['day2', 'orange'],
['day3', 'noodle'],
['day4', 'milk'],
['day5', 'rice'],
['day6', 'water']
])
function eatFood(day) {
eat(foodMap.get(day))
}
对象和 map 的差别主要是顺序不同,然后 map 的数量可以通过 map.size 拿到,并且 map 的键不止是字符串。 这种方式的好处在多条件下更加明显,回到上面的一个例子:
function eat(food) {
console.log('eat food:', food)
}
function play(item) {
console.log('play', item)
}
function getFood(sex, day) {
if (sex === 'boy') {
if (day === 'day0') {
eat('apple')
play('computer')
} else if (day === 'day1') {
eat('banana')
play('basketball')
} else if (day === 'day2') {
eat('orange')
play('baseball')
} else if (day === 'day3') {
eat('noodle')
play('football')
} else if (day === 'day4') {
eat('milk')
play('pingpong')
} else if (day === 'day5') {
eat('rice')
play('golf')
} else if (day === 'day6') {
eat('water')
play('volleyball')
}
} else {
if (day === 'day0') {
eat('apple1')
} else if (day === 'day1') {
eat('banana1')
} else if (day === 'day2') {
eat('orange1')
} else if (day === 'day3') {
eat('noodle1')
} else if (day === 'day4') {
eat('milk1')
} else if (day === 'day5') {
eat('rice1')
} else if (day === 'day6') {
eat('water1')
}
play('makeUp') // 女生肯定天天化妆 }
}
在多个条件的情况下,代码量会成倍增加,很是难看。但是如果我们用 map 来做的话:
function eat(food) {
console.log('eat food:', food)
}
function play(item) {
console.log('play', item)
}
const map1 = new Map([
['day0_boy', ['apple', 'computer']],
['day1_boy', ['banana', 'basketball']],
['day2_boy', ['orange', 'baseball']],
['day3_boy', ['noodle', 'football']],
['day4_boy', ['milk', 'pingpong']],
['day5_boy', ['rice', 'golf']],
['day6_boy', ['water', 'volleyball']],
['day0_girl', ['apple1', 'makeUp']],
['day1_girl', ['banana1', 'makeUp']],
['day2_girl', ['orange1', 'makeUp']],
['day3_girl', ['noodle1', 'makeUp']],
['day4_girl', ['milk1', 'makeUp']],
['day5_girl', ['rice1', 'makeUp']],
['day6_girl', ['water1', 'makeUp']]
])
function foodAndPlay(day, sex) {
eat(map1.get(`${day}_${sex}`)[0])
play(map1.get(`${day}_${sex}`)[1])
}
这样写简洁易懂,上面的那种用对象也可以实现,下面这种就只能通过 map 了,因为对象的 key 只能是字符串:
function eat(food) {
console.log('eat food:', food)
}
function play(item) {
console.log('play', item)
}
const map2 = new Map([
[{day: 'day0', sex: 'boy'}, ['apple', 'computer']],
[{day: 'day1', sex: 'boy'}, ['banana', 'basketball']],
[{day: 'day2', sex: 'boy'}, ['orange', 'baseball']],
[{day: 'day3', sex: 'boy'}, ['noodle', 'football']],
[{day: 'day4', sex: 'boy'}, ['milk', 'pingpong']],
[{day: 'day5', sex: 'boy'}, ['rice', 'golf']],
[{day: 'day6', sex: 'boy'}, ['water', 'volleyball']],
[{day: 'day0', sex: 'girl'}, ['apple1', 'makeUp']],
[{day: 'day1', sex: 'girl'}, ['banana1', 'makeUp']],
[{day: 'day2', sex: 'girl'}, ['orange1', 'makeUp']],
[{day: 'day3', sex: 'girl'}, ['noodle1', 'makeUp']],
[{day: 'day4', sex: 'girl'}, ['milk1', 'makeUp']],
[{day: 'day5', sex: 'girl'}, ['rice1', 'makeUp']],
[{day: 'day6', sex: 'girl'}, ['water1', 'makeUp']]
])
function foodAndPlay(day, sex) {
const result = [...map2].filter(([key, value]) => (key.day === day && key.sex === sex))
result.forEach(([key, value] => {
eat(value[0])
play(value[1])
}))
}
上面的result.forEach方法可以直接换成下面这个,不过可能有点语义上的不友好:
eat(result[0][1][0])
play(result[0][1][1])
现在需求改了,小姐姐们为了减肥,决定每天都只喝水,那么 map 就会变成下面这样:
const map3 = new Map([
[{day: 'day0', sex: 'boy'}, ['apple', 'computer']],
[{day: 'day1', sex: 'boy'}, ['banana', 'basketball']],
[{day: 'day2', sex: 'boy'}, ['orange', 'baseball']],
[{day: 'day3', sex: 'boy'}, ['noodle', 'football']],
[{day: 'day4', sex: 'boy'}, ['milk', 'pingpong']],
[{day: 'day5', sex: 'boy'}, ['rice', 'golf']],
[{day: 'day6', sex: 'boy'}, ['water', 'volleyball']],
[{day: 'day0', sex: 'girl'}, ['water1', 'makeUp']],
[{day: 'day1', sex: 'girl'}, ['water1', 'makeUp']],
[{day: 'day2', sex: 'girl'}, ['water1', 'makeUp']],
[{day: 'day3', sex: 'girl'}, ['water1', 'makeUp']],
[{day: 'day4', sex: 'girl'}, ['water1', 'makeUp']],
[{day: 'day5', sex: 'girl'}, ['water1', 'makeUp']],
[{day: 'day6', sex: 'girl'}, ['water1', 'makeUp']]
}
可以看到,小姐姐们每一天都是重复的,那这样写其实很浪费,怎么办呢:
function eat(food) {
console.log('eat food:', food)
}
function play(item) {
console.log('play', item)
}
const map3 = new Map([
[/^boy_day0$/, ['apple', 'computer']],
[/^boy_day1$/, ['banana', 'basketball']],
[/^boy_day2$/, ['orange', 'baseball']],
[/^boy_day3$/, ['noodle', 'football']],
[/^boy_day4$/, ['milk', 'pingpong']],
[/^boy_day5$/, ['rice', 'golf']],
[/^boy_day6$/, ['water', 'volleyball']],
[/^girl_day[0-6]$/, ['water1', 'makeUp']]
])
function foodAndPlay(day, sex) {
const result = [...map3].filter(([key, value]) => (key.test(`${sex}_${day}`)))
result.forEach(([key, value]) => {
eat(value[0])
play(value[1])
})
}
利用正则来实现条件,是不是很赞! 其实我以前就写过,比如对代码转义来减少 XSS 攻击:
常规写法:
function transformHtml(str) {
return str.replace(/[&<>'"]/g, (item) => {
switch (item) {
case '&':
return '&';
case '
return '<';
case '>':
return '>';
case '’':
return ''';
case '"':
return '"'
}
})
}
escapeHTML('') // "<script>1</script>"
对象写法:
const escapeHTML = str =>
str.replace(
/[&<>'"]/g,
tag =>({'&': '&', '': '>', "'": ''', '"': '"' }[tag] || tag)
);
escapeHTML('') // "<script>1</script>"
还有一点,关于函数返回值:
// 记住一句,有花括号就要 returnlet fn1 = function (a) {
a
}
let fn2 = function (a) {
return a
}
let fn3 = (a) => (a)
let fn4 = (a) => { a }
let fn5 = (a) => {return a}
fn1(1) // undefinedfn1(2) // 1fn1(3) // 1fn1(4) // undefinedfn1(5) // 1
完。