JavaScript 流程控制
条件判断
if...
js
if (条件) {
// ...
}
if...else...
js
if (条件) {
// ...
} else {
// ...
}
提前返回 ( Early Return / Early Exit )
过多的if...else
嵌套会降低代码的可读性,建议先判断不符合的条件并直接return
提前返回
js
function 函数() {
if (不满足的条件) {
return;
}
// ...
}
if...else if...
线性判断每一个条件后执行符合的代码块中的逻辑
对于处理多个值的匹配判断时,则建议使用switch...case...
js
if (条件1) {
// ...
} else if (条件2) {
// ...
} else if (条件3) {
// ...
}
if...else if...else...
线性判断每一个条件后执行符合的代码块中的逻辑
对于处理多个值的匹配判断时,则建议使用switch...case...
js
if (条件1) {
// ...
} else if (条件2) {
// ...
} else if (条件3) {
// ...
} else {
// ...
}
switch...case..
通过跳转表直接执行值匹配的case
子语句中的逻辑
分支条件过多时执行效率以及代码的可读性远远优于if...else if...
js
switch (数据) {
case 值1:
// ...
break;
case 值2:
case 值3:
// ...
break;
default:
// ...
}
不建议直接在case
子语句中直接定义变量或常量,否则报错
若非要使用则需要通过let
、const
定义并将其包裹在一个代码块中
js
switch (数据) {
case 值: {
const 变量 = 值;
let 变量 = 值;
// ...
break;
}
default: {
const 变量 = 值;
let 变量 = 值;
// ...
}
}
循环遍历
while...
js
while (条件) {
// ...
// 中止条件的变量迭代
}
例子:遍历打印 10 次
js
let num = 0;
while (num < 10) {
console.log(num);
num++;
}
do...while...
js
do {
// ...
// 中止条件的变量迭代
} while (条件);
例子:利用循环计控制器变量重复展示浏览器 alert 信息
js
let result = "";
do {
result = prompt("你爱我吗?");
} while (result !== "是的");
for...
最传统的循环方法,执行效率快但是在遍历数组时不如内置 API 方便
js
for (let 循环计时器变量 = 初始值; 判断循环计时器; 更新循环计时器) {
// ...
}
例子:打印九九乘法表
利用双重
for
循环
js
for (let i = 1; i <= 9; i++) {
let line = "";
for (let j = 1; j <= i; j++) {
line += `${j} * ${i} = ${i * j}\t`;
}
console.log(line);
}
// 1 * 1 = 1
// 1 * 2 = 2 2 * 2 = 4
// 1 * 3 = 3 2 * 3 = 6 3 * 3 = 9
// 1 * 4 = 4 2 * 4 = 8 3 * 4 = 12 4 * 4 = 16
// 1 * 5 = 5 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25
// 1 * 6 = 6 2 * 6 = 12 3 * 6 = 18 4 * 6 = 24 5 * 6 = 30 6 * 6 = 36
// 1 * 7 = 7 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49
// 1 * 8 = 8 2 * 8 = 16 3 * 8 = 24 4 * 8 = 32 5 * 8 = 40 6 * 8 = 48 7 * 8 = 56 8 * 8 = 64
// 1 * 9 = 9 2 * 9 = 18 3 * 9 = 27 4 * 9 = 36 5 * 9 = 45 6 * 9 = 54 7 * 9 = 63 8 * 9 = 72 9 * 9 = 81
例子:对数组进行冒泡排序 ( Bubble Sort )
利用双重
for
循环
js
const list = [3, 1, 4, 2, 5];
for (let i = 0; i < list.length - 1; i++) {
for (let j = 0; j < list.length - 1 - i; j++) {
if (list[j] > list[j + 1]) {
let temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
}
}
}
console.log(list); // [1, 2, 3, 4, 5]
例子:对数组进行选择排序 ( Select Sort )
js
const list = [3, 1, 4, 2, 5];
for (let i = 0; i < list.length - 1; i++) {
let minElementIndex = i;
for (let j = i + 1; j < list.length; j++) {
if (list[j] < list[minElementIndex]) {
minElementIndex = j;
}
}
let temp = list[i];
list[i] = list[minElementIndex];
list[minElementIndex] = temp;
}
console.log(list); // [1, 2, 3, 4, 5]
for...in...
可用于遍历一个键值对对象的所有可枚举属性
js
for (let key in 对象) {
// ...
}
不建议使用
- 执行速度慢性能较差,因为会遍历所有的可枚举属性可能会导致不必要的性能开销
- 会遍历对象的原型链,比较危险,若非要用不可则必须使用
hasOwnProperty()
来避免遍历原型链
例子:使用hasOwnProperty()
来确保只遍历对象自身的属性而不是原型链上的属性
js
const obj = { a: 1, b: 2 };
Object.prototype.c = 3;
for (let key in obj) {
console.log(key, obj[key]);
}
// "a" 1
// "b" 2
// "c" 3
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key]);
}
}
// "a" 1
// "b" 2
for...of...
可用于遍历一个可迭代的对象 ( 数组、字符串、Map、Set、DOM集合 )
不能用于遍历键值对对象,若非使要用则需要先将其转为数组
js
for (const key of 可迭代的对象) {
// ...
}
for (const key of Object.keys(键值对对象)) {
// ...
}
for (const value of Object.values(键值对对象)) {
// ...
}
for (const [key, value] of Object.entries(键值对对象)) {
// ...
}
数组的内置 API
遍历数组时更建议使用其内置 API
forEach()
every()
some()
filter()
map()
find()
findIndex()
reduce()
异常处理
常见异常类型
SyntaxError
语法错误TypeError
类型错误ReferenceError
引用错误RangeError
边界错误URIError
URL 错误
try...catch...finally
可用于捕获异常
js
try {
// ...
} catch (error) {
// ...
} finally {
// ...
}
throw
可用于实现抛出异常
js
// ...
throw new Error();
throw new Error("自定义信息");
// ...
debugger
debugger
语句可以在代码中的指定位置打一个断点
断点不会对代码产生任何影响,仅在调试时程序会在此处暂停执行
js
// ...
debugger;
// ...