面向过程-3:分支if...else / 调试 / 模糊需求 / switch...case

更多
2021年05月27日 18点28分 作者:叶飞 修改

为了演示方便,需要首先告诉大家如何进行

断点调试

断点:让程序运行到某一行代码的时候停下来,便于我们观察其内部运行状况

调试:通过不断的整尝,修复(fix)程序的缺陷(bug)

浏览器F12演示:

  • 运行code.js文件,其中开始使用console.log(')
  • 在Sources找到JavaScript代码
  • 设置断点,刷新页面,停在断点
  • F10继续运行到下一行
  • F8运行一直运行到下一个断点


if

中文就是:如果(if)...否则(else)……的意思

假设我们要判断一个数是不是正数:

var number = -1; //或者 number = 1 
if (number >= 0) { 
    console.log('正数'); 
}

if后面可以是结果为bool值的表达式,也可以直接是一个bool值变量。

	var number = -1,
                //可以用一个var声明多个变量,
                //而且后面的变量可以使用前面的变量进行运算
		isPositive = (number >= 0);  
	if (!isPositive) { 

这时候注意:如果if后面直接就是一个bool值,不要用这种菜鸟写法:

if(isPositive == true)
if(isPositive != true)
//而是:
if(isPositive)    //直接读成:是正数
if(!isPositive)   //直接读成:不是正数


else

提高性能

在上述需求(大于等于0显示为正数)的基础上再加一个判断:小于0显示为负数。该怎么写?
if (number >= 0) { 
    console.log('正数'); 
} 
if (number < 0) { 
    console.log('负数'); 
}

这样写运行结果没有错,但是有一个性能 上的问题:

假设 number = 100,它通过了 number > 0 的判断,输出:正数。正数就永远不可能为负数,还需要再走一次 number < 0 的判断么?

断点演示:

所以,这种情况,我们应该使用 else:

if (number >= 0) { 
    console.log('正数'); 
}else {
    console.log('负数'); 
}

这里的else不会进行判断:只要没有满足前面的if条件,马上就会进入else分支。

注意:if和else中间不能再插入任何语句。

减少bug,增加可读性

if并不强制要求必须搭配else,但是飞哥强烈建议你只要写了if,就总是要用else兜底!

这有两个作用:

  • 逻辑更严密,用else兜底,让分支没有漏网之鱼,^_^
  • 要是else里面就没啥可做的呢?飞哥建议,让else的{}空着,或者加一个小注释//else nothing。目的只有一个:增加代码可读性。让其他人明确的知道:你是考虑到else情况的,else的时候就是不需要任何处理的。
    if (passed)
    {
        console.log("正数");
    }//else nothing

再次暴露你个菜鸟

尤其需要注意的是,不要出现这样的代码:

var number = 1,
    isPositive = false;
if (number > 0) {
    isPositive = true;
} else {
    isPositive = false;
}

孽徒!逐出师门,屎山一样的代码,居然说“看不出啥问题”……

居然和我犟可维护性!怎么就没有可维护性了?

var isPositive = number > 0;
if (isPositive) {
	//添加的逻辑
}


花括号{}

注意上面所有代码,无论是 if() 还是 else ,后面都跟了{}。

但因为历史原因,如果if/else后面只有一句话,也可以(但强烈建议!)省略掉这个{}

@想一想@:为什么?

	var score = 98;
	if (score > 60)
		console.log("及格");  //单行语句符合语法
	else
		console.log("不及格");    //但是不推荐
		console.log("补考");	//这句话就会有问题


条件运算符

上面的if...else...可以进一步重构:

var result; 
if (a >= 0) { 
    result = '正数'; 
} else { 
    result ='负数'; 
} 
console.log(result);
重构:在不改变代码运行结果的前提下,对代码进行调整优化——是提高代码质量的重要手段!

@想一想@:这算是优化么?还多了一行呢……

因为这种if...else...的情形非常常见,就产生了这种写法:

var result = a > 0     //条件 
    ? '正数'     //条件为真时取值 
    : '负数';     //条件为假时取值

这是一个由问号(?)和冒号(:)组成的三元(目)运算符。
PS:元/目:参与运算的对象(值/变量)的个数


嵌套组合

上面的例子我们忽略了一点:如果 number=0,那么a既不是负数,也不是整数,我们应该直接输出“零”,这怎么实现?

  1. 方案一:循环嵌套。
    if (number == 0) {
        console.log('零');
    } else {
        if (number > 0) {
            console.log('正数');
        } else { 
            console.log('负数');
        }
    }
  2. 方案二:else if()
    if (number === 0) {
        console.log('零');
    } else if (number > 0) {
        console.log('正数');
    } else {
        console.log('负数');
    }

嵌套和else if()可以自由组合,一直“分支”下去,可以实现更复杂的功能、完成复杂的需求。但复杂的层层分支是程序员的噩梦,o(╥﹏╥)o

如何选择?一般来说:

  • 如果分支的条件是同类型的、并列的(如上述例子,将同一个变量number和0进行比较),使用else if()可以减少层级嵌套,优先选用
  • 否则,可以考虑if...else嵌套,比如:
    	if (score == 0) {  //外层比较的是score
    		console.log('零');
    	} else {
    		if (age > 0) {	//内层比较的是age
    			console.log('正数');
    		} else { 
    			console.log('负数');
    		}
    	}

复杂业务需求

比如,源栈可以根据学习时间打折优惠:

  • 4周以下:原价每周888元
  • 25周(满课时):包学会,定价19888元
  • 12周以上:8折
  • 8周以下:9折

代码如何实现?(一起写)

    if (weeks < 4) {
        console.log("学费是:" + 888 * weeks);
    } else if (weeks == 25) {
        console.log("学费是:17888");
    } else if (weeks > 12) {
        console.log("学费是:" +888 * weeks * 0.8);
    } else if (weeks < 8) {
        console.log("学费是:" +888 * weeks * 0.9);
    }

菜鸟 vs 老鸟

凡是拿着需求就开始写的,都是菜鸟!

上述需求是有问题的:

  • 4周8周以上以下包含不包含4周8周本身?
  • 4周到8周如何处理?
  • 如果week<0,或者weeks>25,甚至是一些非数值输入怎么办?
  • ……

写代码之前,首先明确需求——这就是老鸟和菜鸟的区别!

你以后大概率上会发现:作为一个程序员在工作中伤你最深的、你最最头痛和痛苦的,不是“技术”,而是“需求”——模糊不清的需求、千变万化的需求、稀奇古怪的需求……

整理

补充完善好需求之后,再经过整理(尤其注意顺序/层级)后的代码如下所示:

	if(weeks<0 || weeks>25){
		console.log("越界啦……");
	}else{
		if (weeks < 4) {
			console.log("学费是:" + 888 * weeks);
		}else if (weeks < 8) {
			console.log("学费是:" +888 * weeks * 0.9);
		}else if (weeks < 12){
			console.log("学费是:" +888 * weeks * 0.95);
		}else if (weeks < 25) {
			console.log("学费是:" +888 * weeks * 0.8);
		}else if (weeks == 25) {
			console.log("学费是:17888");
		}else{
			console.log("咦?怎么回事?weeks=" + weeks);	
		}			
	}
if...else的整理,是程序员的基本功。从一开始就要严格要求自己:

程序不是能跑就行,一定要干净整洁通畅……或者总结为:可读性强!


switch...case

除if...else以为,还有一种分支:

var grade = 2;
switch (grade)
{
    case 1:
        console.log("发10个红包");
        break;
    case 2:
        console.log("发5个红包");
        break;
    case 3:
        console.log("没有红包了");
        break;
    default:
       console.log("怎么回事?");
        break;
}


整段代码的意思就是,根据grade的值进行分支:

  1. 如果grade的值等于1,输出"发10个红包";
  2. 如果grade的值等于2,输出"发5个红包";
  3. 如果grade的值等于3,输出"没有红包了";
  4. 如果grade的值不等于上面的任何的一个值,输出"怎么回事?"

这种逻辑其实用if...else...也可以实现,类似于:

if(grade == 1){
	console.log("发10个红包");
}else if(grade ==2){
	console.log("发5个红包");
}else if //...
但是switch...case看起来更整洁一些。


另外要注意以下几点:

  • 只能进行“等值”运算,也就是说只能判断switch()中的值是否等于case后面的值,不能进行大于小于等其他运算。比如这样:
    case grade > 1: //不要这样!会崩
  • 代码执行时从上往下比较,所以顺序很重要。
  • 不要忘记default,相当于if...else...中最后兜底的else,应该是在上述所有case条件都不满足的情况下才执行的,所以应该放在最后。
  • 不要忘记break,break意味着跳出switch域。

如果两个case之间没有break只有业务逻辑语句,就会出问题(JavaScript莫名其妙,其他语言报编译错误);

如果两(多)个case之间没有任何其他语句,这些case条件构成一种“或”的关系,比如:

switch (grade)
{
    case 1:
    case 2:
        console.log("发5个红包");
        break;
    case 3:


演示:无论grade等于1或者2,都是输出“发5个红包”


作业

  1. 声明变量age(年龄),写一段代码能根据age输出文本:成年(满18岁),或者未成年(未满18岁)
    var age /*补足*/;
    if(age /*补足*/ 18){
        alert(/*补足*/);
    }/*补足*/
  2. 写一段代码,能够根据score(成绩)输出文本:
    • 60以下:不及格
    • 80以上:优秀
    • 60-80:及格
注意:审查是否存在模糊的需求。如果存在,予以修正,作为注释包含在代码中。
分支 循环 数组
赞: 0 踩: 0

打赏
已收到打赏的 帮帮币

你的 打赏 非常重要!
为了保证文章的质量,每一篇文章的发布,都已经消耗了作者 1 枚 帮帮币
没有“帮帮币”,作者无法发布新的文章。

全系列阅读
评论 / 0

编程基础


项目管理相关

需求发布、开发规划、部署、测试,源代码版本管理(git)等……

逸闻史话

认识计算机

编程语言

数据结构和算法

Web开发基础

全部
关键字



帮助

反馈