语句是JavaScript程序的基本构建单元,它们控制着程序的执行流程。如果说表达式是程序中的“词汇”,那么语句就是“句子”,它们告诉JavaScript引擎应该执行什么操作以及按照什么顺序执行。理解各种语句类型及其使用方法,是掌握JavaScript程序控制逻辑的关键。
在JavaScript中,语句通常以分号结尾,虽然分号在某些情况下可以省略,但养成添加分号的习惯有助于避免潜在的问题。程序的执行过程就是按照语句的顺序,从上到下依次执行每条语句,除非遇到改变执行流程的控制语句。

最简单的语句类型就是表达式语句,它由一个表达式加上分号组成。这类语句的主要作用是产生副作用,比如修改变量的值、调用函数或者改变对象的状态。虽然表达式语句看起来简单,但它们在实际编程中使用频率很高。
赋值语句是表达式语句中最常见的一种。当我们需要将某个值存储到变量中时,就会使用赋值语句。例如,在开发一个学生管理系统时,我们可能需要这样的代码:
studentName = "张小明";
studentAge = 18;
totalScore = mathScore + englishScore + chineseScore;递增和递减运算符也常常作为独立的语句使用。在处理计数器或者循环变量时,这类语句特别有用:
pageNumber++;
itemCount--;
score += bonusPoints;函数调用也是表达式语句的重要组成部分。在Web开发中,我们经常需要调用各种函数来实现特定的功能:
displayWelcomeMessage();
updateUserInterface();
console.log("程序开始执行");需要注意的是,只有那些产生副作用的表达式才适合作为独立语句使用。如果一个表达式只是计算某个值而不产生任何副作用,那么将其作为独立语句就没有实际意义。
当我们需要在期望单个语句的地方使用多个语句时,复合语句就发挥了重要作用。复合语句使用一对花括号将多个语句组合在一起,形成一个语句块。这种结构在控制流语句中特别常见。
{
let currentTime = new Date();
let greeting = "今天是 " + currentTime.toDateString();
console.log(greeting);
updateTimeDisplay(currentTime);
}复合语句让我们能够在循环体、条件分支或函数体中包含多个操作。值得注意的是,与其他一些编程语言不同,JavaScript中的复合语句并不创建新的变量作用域,变量的作用域仍然由函数或全局环境决定。
与复合语句相对的是空语句,它只包含一个分号,不执行任何操作。空语句在某些特殊情况下很有用,比如当我们需要创建一个没有循环体的循环时:
// 寻找数组中第一个空元素的位置
for (index = 0; index < dataArray.length && dataArray[index] != null; index++);虽然空语句有其用途,但在使用时要格外小心,因为意外的分号可能导致程序逻辑错误。
声明语句用于创建变量和函数,它们为程序中的其他语句提供了操作的基础。通过声明语句,我们可以定义程序中需要使用的标识符,并为它们分配内存空间。
变量声明是最基础的声明语句。使用var关键字,我们可以声明一个或多个变量,并可选择性地为它们赋初值:
var userName;
var userAge = 25;
var firstName = "李", lastName = "明";
var totalAmount = price * quantity, taxAmount = totalAmount * 0.1;变量声明具有"提升"的特性,这意味着变量的声明会被移动到其所在作用域的顶部。然而,只有声明被提升,赋值操作仍然在原来的位置执行。这个特性有时会导致一些意外的行为,因此理解变量提升对于编写可靠的JavaScript代码非常重要。
函数声明是另一种重要的声明语句。通过function关键字,我们可以定义可重用的代码块:
function calculateArea(length, width) {
return length * width;
}
function greetUser(name) {
let welcomeMessage = "欢迎," + name + "!";
console.log(welcomeMessage);
return welcomeMessage;
}函数声明不仅创建了函数对象,还将函数名作为变量进行了声明。与变量声明类似,函数声明也具有提升特性,但函数声明的提升更为完整——整个函数定义都会被提升到作用域顶部。
条件语句是程序中的决策点,它们根据特定条件的真假来决定程序的执行路径。条件语句让程序能够根据不同的情况做出不同的响应,这是实现程序智能行为的基础。
if语句是最基本的条件语句。它根据条件表达式的结果来决定是否执行某段代码。在实际应用中,if语句经常用于输入验证、状态检查和业务逻辑判断:
if (userAge >= 18) {
console.log("用户已成年,可以注册账户");
allowRegistration = true;
}
if (!userEmail) {
console.log("请提供有效的邮箱地址");
showErrorMessage("邮箱地址不能为空");
}if/else语句用于在程序中实现条件判断和分支选择。它提供了双分支的控制结构:当条件表达式的结果为真(true)时,执行if代码块中的语句;当条件为假(false)时,执行else代码块中的语句。其基本语法如下:
if (currentHour < 12) {
greeting = "上午好!";
} else {
greeting = "下午好!";
}
if (temperature > 30) {
weatherAdvice = "今天很热,记得多喝水!";
} else {
weatherAdvice = "天气还不错,适合外出活动。";
}在实际开发中,我们经常会遇到需要根据不同条件执行不同操作的场景。此时,单独的if或if/else结构可能会让代码变得冗长且难以维护。为了解决这种多条件分支的需求,JavaScript 提供了 else if 结构。通过在 if 和 else 之间插入一个或多个 else if 分支,可以让代码根据不同的条件有条理地选择执行路径。每个条件都会依次判断,只有第一个为真的分支会被执行,其余分支会被跳过,这样可以让多条件判断变得更加清晰和易于阅读。
if (score >= 90) {
grade = "优秀";
bonus = 100;
} else if (score >= 80) {
grade = "良好";
bonus = 50;
} else if (score >= 70) {
grade = "中等";
bonus = 20;
} else {
grade = "需要改进";
bonus = 0;
}switch语句用于根据某个表达式(通常是变量)的不同取值,执行不同的代码分支。它为多条件分支提供了一种结构化且易读的写法,尤其适合处理那些需要针对同一个变量的不同取值分别执行不同操作的场景。与多个if/else语句相比,switch语句可以让代码更加简洁、清晰,避免了重复的条件判断。其基本语法是:先对表达式求值,然后依次与每个case的值进行严格相等(===)比较,匹配到对应case时执行其代码块。如果没有任何case匹配,则执行default分支(如果有的话)。通常每个case后面会加上break语句,以防止“穿透”到下一个case。
switch (userRole) {
case "admin":
showAdminPanel();
enableAllFeatures();
break;
case "moderator":
showModerationTools();
enableBasicFeatures();
break;
case "user":
showUserInterface();
break;
default:
showLoginForm();
break;
}在switch语句中,break语句非常重要,它防止代码"穿透"到下一个case分支。如果忘记使用break,程序会继续执行后续的case分支,这通常不是我们想要的行为。
循环语句让程序能够重复执行某段代码,直到满足特定的终止条件。循环是处理重复任务的强大工具,无论是遍历数据集合、重复计算还是等待特定条件的出现。
while循环是最基本的循环结构。它的工作流程如下:
这种结构非常适合在循环开始前就需要判断是否继续执行的场景。例如,倒计时、等待某个条件成立等。只有当条件满足时,循环体才会被执行一次或多次,否则循环体可能一次都不会执行。
let countdown = 10;
while (countdown > 0) {
console.log("倒计时:" + countdown);
countdown--;
}
console.log("时间到!");do/while循环与while循环的主要区别在于条件判断的时机:while循环是在每次循环开始前判断条件,只有条件为真时才会执行循环体;而do/while循环则是先执行一次循环体, 然后再判断条件是否继续循环。这意味着,无论条件是否为真,do/while循环的循环体至少会被执行一次。
这种特性在某些需要“先做一次,再判断是否继续”的场景下非常有用。 例如,用户输入验证:你希望至少提示用户输入一次,然后根据输入的内容决定是否继续要求输入。do/while循环可以很好地满足这种需求:
let userInput;
do {
userInput = prompt("请输入一个正数:");
} while (userInput <= 0);
console.log("您输入的数字是:" + userInput);for循环是一种结构紧凑、功能强大的循环语句,适用于需要明确指定“初始化变量”、“循环条件判断”和“每轮循环后变量更新”这三个步骤的场景。它的语法结构如下:
for (let day = 1; day <= 30; day++) {
console.log("第 " + day + " 天的任务");
performDailyTask(day);
}
for (let row = 0; row < tableData.length; row++) {
for (let col = 0; col < tableData[row].length; col++) {
processTableCell(tableData[row][col]);
}
}for/in循环专门用于遍历对象的属性。它为处理对象属性提供了简洁的语法:
let studentInfo = {
name: "王小华",
age: 20,
major: "计算机科学",
grade: "大二"
};
for (let property in studentInfo) {
console.log(property + ": " + studentInfo[property]);
}需要注意的是,for/in循环遍历的是对象的可枚举属性,包括继承的属性。在使用时要考虑是否需要检查属性是否为对象自有的属性。
跳转语句改变程序的正常执行流程,让程序能够跳转到代码的其他位置。这些语句为程序提供了更灵活的控制机制,但使用时需要谨慎,以免影响代码的可读性。
break语句用于立即退出最内层的循环或switch语句。在处理搜索、数据验证或者需要提前终止循环的场景中,break语句很有用:
let targetFound = false;
for (let i = 0; i < dataList.length; i++) {
if (dataList[i] === targetValue) {
console.log("在位置 " + i + " 找到目标值");
targetFound = true;
break;
}
}
if (!targetFound) {
console.log("未找到目标值");
}continue语句用于跳过当前循环迭代的剩余部分,直接进入下一次迭代。这在需要跳过某些特定情况时很有用:
for (let num = 1; num <= 20; num++) {
if (num % 2 === 0) {
continue; // 跳过偶数
}
console.log("奇数:" + num);
}return语句用于从函数中返回值并终止函数的执行。return语句是函数与外部代码通信的主要方式,它可以将计算结果传递给调用者,也可以用于提前终止函数执行:
function calculateDiscount(price, discountRate) {
if (price <= 0) {
return 0; // 价格无效,返回0
}
let discountAmount = price * discountRate;
return discountAmount;
}
function validateEmail(email) {
if (!email.includes("@")) {
return false;
}
return true;
}标签语句可以为语句添加标识符,配合break和continue使用可以实现更精确的跳转控制。例如,下面的代码使用标签语句和break语句实现了跳出多层循环的需求:
outerLoop: for (let i = 0; i < 5; i++) {
for (let j = 0; j < 5; j++) {
if (i * j > 10) {
break outerLoop; // 跳出外层循环
}
console.log(i + " * " + j + " = " + (i * j));
}
}异常处理是提升程序稳定性和用户体验的重要手段。通过合理的异常处理,程序不仅可以避免在遇到错误时直接崩溃,还能给出有意义的错误提示,甚至尝试恢复或采取补救措施。 JavaScript为开发者提供了完善的异常处理机制,包括主动抛出异常和捕获异常两大部分。
在JavaScript中,异常通常指的是程序运行过程中出现的错误,比如语法错误、类型错误、网络请求失败等。合理的异常处理可以让程序在遇到这些问题时,依然保持可控和稳定。
throw语句用于在程序中主动抛出一个异常。当检测到某些不符合预期的条件时,可以使用throw语句来中断当前代码的执行,并将错误信息传递到调用者或异常处理机制中
。throw后面可以抛出任意类型的表达式,通常建议抛出Error对象,这样可以包含更丰富的错误信息和堆栈跟踪,便于调试和定位问题。
常见的用法包括参数校验、业务逻辑判断等。例如:
下面是throw语句的基本用法示例:
function divide(a, b) {
if (b === 0) {
throw new Error("除数不能为零");
}
return a / b;
}
function setUserAge(age) {
if (age < 0 || age > 150) {
throw new Error("年龄必须在0到150之间");
}
this.age = age;
}try/catch/finally语句为JavaScript提供了完整的异常捕获与处理流程。其结构由三个部分组成:
整个流程如下:先执行try块,如果没有异常则跳过catch,直接执行finally;如果try块中有异常,则跳转到catch处理,catch执行完后再进入finally。即使catch块中再次抛出异常,finally依然会被执行。
示例:
try {
let userData = JSON.parse(userInputString);
processUserData(userData);
saveToDatabase(userData);
} catch (error) {
console.log("处理用户数据时发生错误:" + error.message);
showErrorNotification("数据格式错误,请检查输入");
} finally {
hideLoadingIndicator();
enableUserInterface();
}JavaScript的严格模式通过"use strict"指令启用,它为JavaScript提供了更严格的语法检查和更安全的执行环境。在严格模式下,一些潜在的错误会被当作异常抛出,而不是默默地被忽略。
"use strict";
function calculateTotal(items) {
let total = 0;
// 在严格模式下,必须显式声明变量
for (let i = 0; i < items.length; i++) {
total += items[i].price;
}
return total;
}严格模式的主要好处包括禁止使用未声明的变量、禁止删除变量和函数、禁止重复的参数名等。这些限制有助于编写更安全、更可维护的代码。
debugger语句为调试提供了程序化的断点设置。当开发者工具打开时,程序执行到debugger语句会自动暂停,方便开发者检查程序状态:
function complexCalculation(data) {
let result = 0;
for (let item of data) {
if (item.value < 0) {
debugger; // 在这里暂停,检查为什么会有负值
}
result += item.value * item.multiplier;
}
return result;
}userName = "张三"; 这行代码属于哪种类型的语句?完成以下条件语句,根据分数输出相应的等级:
let score = 85;
if (score >= 90) {
console.log("_______");
} else if (score >= 80) {
console.log("_______");
} else {
console.log("_______");
}let score = 85;
if (score >= 90) {
console.log("优秀");
} else if (score >= 80) {
console.log("良好");
} else {
console.log("需要努力");
}if/else if/else语句用于多条件分支判断。在这个例子中,分数85满足score >= 80的条件,所以会输出"良好"。条件会从上到下依次判断,只有第一个为真的分支会被执行。
修正下面的循环代码,使其能够正常结束:
let i = 0;
while (i < 5) {
console.log("第 " + i + " 次循环");
// 这里缺少什么?
_______
}let i = 0;
while (i < 5) {
console.log("第 " + i + " 次循环");
i++; // 递增循环变量,否则会无限循环
}while循环需要在循环体内修改循环条件,否则会形成无限循环。在这个例子中,需要递增变量i,使其最终不满足i < 5的条件,循环才能正常结束。
填写异常处理代码,完成try/catch/finally结构:
try {
let result = 10 / 0;
console.log(result);
} _______ (error) {
console.log("发生错误:" + error.message);
} _______ {
console.log("清理工作完成");
}try {
let result = 10 / 0;
console.log(result); // 输出:Infinity
} catch (error) {
console.log("发生错误:" + error.message);
} finally {
console.log("清理工作完成");
}try/catch/finally是异常处理的完整结构:
try块包含可能出错的代码catch块捕获并处理异常,参数是异常对象finally块无论是否发生异常都会执行注意:10 / 0在JavaScript中结果是Infinity,不会抛出异常。如果要测试异常处理,可以使用throw new Error("错误信息")。
完成switch语句,根据星期数输出对应的星期名称:
let dayOfWeek = 3;
switch (_______) {
case 1:
console.log("星期一");
_______;
case 2:
console.log("星期二");
_______;
_______:
console.log("其他日期");
}let dayOfWeek = 3;
switch (dayOfWeek) {
case 1:
console.log("星期一");
break;
case 2:
console.log("星期二");
break;
default:
console.log("其他日期");
}switch语句的要点:
switch后面是要判断的变量或表达式case后面是可能的值break语句防止代码"穿透"到下一个casedefault处理所有不匹配的情况在这个例子中,dayOfWeek为3,不匹配任何case,所以执行default分支,输出"其他日期"。
编写一个学生成绩管理程序,要求:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>学生成绩管理</title>
</head>
<body>
<script>
// 学生信息数组
let students = [
{ name: "张三", score: 95 },
{ name: "李四", score: 85 },
{ name: "王五", score: 75 },
{ name: "赵六", score: 65 }
];
// 根据成绩获取等级
function getGrade(score) {
if (score >= 90) {
return "优秀";
} else if (score >= 80) {
return "良好";
} else if (score >= 70) {
return "中等";
} else if (score >= 60) {
return "及格";
} else {
return "不及格";
}
}
// 处理学生成绩
function processStudent(student) {
try {
// 验证成绩有效性
if (student.score < 0 || student.score > 100) {
throw new Error("成绩必须在0-100之间");
}
if (isNaN(student.score)) {
throw new Error("成绩必须是数字");
}
let grade = getGrade(student.score);
console.log(student.name + ":成绩" + student.score + ",等级" + grade);
} catch (error) {
console.log(student.name + "的数据有误:" + error.message);
}
}
// 循环处理所有学生
for (let i = 0; i < students.length; i++) {
processStudent(students[i]);
}
// 测试异常处理
console.log("\n测试异常处理:");
processStudent({ name: "测试", score: 150 }); // 无效成绩
processStudent({ name: "测试2", score: "abc" }); // 非数字
</script>
</body>
</html>这个例子综合运用了:
通过这个例子,我们可以看到如何将不同的语句类型组合起来,实现完整的程序功能。