系统讲解JavaScript基础语法中的变量声明、循环控制结构与函数封装。结合清晰直观的原理图解与可运行代码实例,剖析作用域、迭代机制及模块化设计要点。
JavaScript基础语法实例:变量、循环与函数代码演示
时间:2026-10-30
浏览:648
文章目录
在 JavaScript 程序开发中,变量、循环与函数是构建所有业务逻辑的三大基石。变量负责在内存中开辟空间并暂存动态数据,循环负责以受控的方式自动重复执行既定逻辑,而函数则将一系列操作封装为可复用、具有明确输入输出的独立模块。本文围绕这三个核心要素,结合实际可运行的代码演示与详细原理剖析,帮助读者建立系统而扎实的 JavaScript 编程认知。
一、核心语法执行流与运行环境准备
JavaScript 是一种解释型、弱类型且基于原型的脚本语言。现代浏览器(如 Chrome、Edge、Firefox)均内置了高性能的 JavaScript 执行引擎(例如 V8、SpiderMonkey),读者无需安装复杂配置即可直接进行语法验证。在浏览器任意页面按下 F12 或右键选择“检查”,切换至 Console(控制台) 选项卡,即可直接键入并回车执行 JavaScript 代码;若在本地拥有 Node.js 运行环境,则可以直接在命令行终端输入 node 进入交互式解释器(REPL)进行测试。
二、变量声明与作用域:var、let 与 const 的本质区别
变量是程序存储与追踪状态的核心手段。在 ECMAScript 6 (ES2015) 规范发布之前,JavaScript 仅支持 var 关键字声明变量。为了解决变量提升、作用域泄漏以及无意覆盖全局变量等设计历史问题,现代规范引入了具备块级作用域的 let 与 const。
1. 三种声明方式的对比
| 关键字 | 作用域级别 | 变量提升现象 | 重复声明 | 重新赋值 |
|---|---|---|---|---|
var |
函数作用域 / 全局 | 存在提升,且初值被初始化为 undefined |
允许在同级作用域重复声明 | 允许重新赋值 |
let |
块级作用域 {} |
存在提升,但处于暂存死区(TDZ),声明前不可访问 | 不允许同级重复声明 | 允许重新赋值 |
const |
块级作用域 {} |
存在提升,但处于暂存死区(TDZ),声明前不可访问 | 不允许同级重复声明 | 只读绑定,不可重新指向新引用 |
2. 变量代码实操演示
// 1. 常量与基础类型
const APP_NAME = "SystemMonitor";
const MAX_CONCURRENT = 5;
// 2. 块级作用域隔离
let currentTaskCount = 0;
if (MAX_CONCURRENT > 0) {
// 这里的 blockScopedToken 仅在当前 if 分支内可见
const blockScopedToken = "TOKEN_" + Math.random().toString(16).slice(2);
currentTaskCount += 1;
console.log("内部生成 Token:", blockScopedToken, "当前任务数:", currentTaskCount);
}
// 尝试在外部访问将抛出 ReferenceError
// console.log(blockScopedToken); // 报错:blockScopedToken is not defined
// 3. 引用类型常量的修改特性
const serverConfig = {
host: "127.0.0.1",
port: 3000,
routes: ["/home", "/api"]
};
// 允许修改对象属性和向数组追加元素
serverConfig.port = 8080;
serverConfig.routes.push("/status");
console.log("更新后的服务器配置:", serverConfig);
// 若尝试使 serverConfig 指向新的对象地址,则会触发只读赋值报错:
// serverConfig = { host: "0.0.0.0" }; // TypeError: Assignment to constant variable.
三、循环控制结构:for、while 与循环跳转控制
循环允许我们以极简洁的代码批量处理大量重复计算。JavaScript 提供了多种形态的循环结构,主要包括基于计数器的标准 for 循环、基于条件成立的 while / do-while 循环,以及针对可迭代对象(如数组、字符串、集合)的 for...of 循环。
1. 核心循环语句概述
- 标准 for 循环:最经典的循环形态,由“初始化语句;条件判定表达式;迭代递增表达式”构成,适合循环次数已知的场景。
- while 循环:进入前先求值条件表达式,若为真则执行循环体;适合等待外部条件改变或循环次数未知的场景。
- do...while 循环:先无条件执行一次循环体,再判定条件表达式;保证至少执行一次。
- for...of 循环:ES6 推荐的集合遍历语法,能够直接取得数组或集合的元素值,相比传统的下标遍历更直观且安全。
- break 与 continue:
break用于立即终止整个循环并跳转到循环体外;continue用于终止本轮迭代并跳过剩余语句,直接进入下一轮循环的步进判定。
2. 循环实操代码演示
// 1. 标准 for 循环遍历与过滤计算
const scores = [88, 59, 94, -1, 76, 60, null, 85];
let validTotal = 0;
let passedCount = 0;
console.log("--- 开始成绩分析 ---");
for (let i = 0; i < scores.length; i++) {
const current = scores[i];
// 遇到空数据 null 时触发 break,提前退出后续扫描
if (current === null) {
console.log(`下标 ${i} 处遇到无效结束标记 null,中止循环`);
break;
}
// 负数值属于录入异常,跳过本轮累加,直接进入下一轮
if (current < 0) {
console.warn(`下标 ${i} 处分数异常(${current}),已跳过`);
continue;
}
validTotal += current;
if (current >= 60) {
passedCount++;
}
}
console.log(`有效总分: ${validTotal}, 及格人数: ${passedCount}`);
// 2. while 循环:模拟资金复利增长直至达到目标
let balance = 1000;
const target = 1500;
const annualRate = 0.08;
let years = 0;
while (balance < target) {
balance *= (1 + annualRate);
years++;
}
console.log(`经过 ${years} 年复利增长,本息达到目标: ¥${balance.toFixed(2)}`);
// 3. 现代化 for...of 循环:直观遍历集合元素
const devTools = ["V8", "Webpack", "Vite", "Babel"];
console.log("工具链清单:");
for (const tool of devTools) {
console.log(" - " + tool);
}
四、函数的声明、参数传递与返回值
函数是组织程序、实现复用和建立抽象边界的核心机制。在 JavaScript 中,函数是“头等公民(First-Class Citizens)”,这意味着函数可以像普通变量一样被传递、作为参数赋予其他函数、或者由函数作为结果返回。
1. 函数常见的三种定义形态
- 函数声明式(Function Declaration):使用
function fnName(params) { ... }形式。具备函数声明整体提升特性,可以在声明语句之前调用。 - 函数表达式(Function Expression):将匿名或具名函数赋值给变量
const fn = function() { ... }。遵循变量的提升规则(受const/let限制),必须先声明后调用。 - 箭头函数(Arrow Function):ES6 引入的简洁语法
const fn = (a, b) => a + b。它不绑定自身的this、arguments,特别适合轻量级数据运算与回调函数。
2. 参数默认值与不定参数(Rest Parameters)
// 1. 默认参数:当调用者未传参或传入 undefined 时生效
function createHttpRequest(url, method = "GET", timeout = 5000) {
return {
url,
method,
timeout,
timestamp: Date.now()
};
}
console.log(createHttpRequest("/api/users"));
// 输出: { url: '/api/users', method: 'GET', timeout: 5000, timestamp: ... }
// 2. Rest 参数:将不定数量的入参汇聚为真实数组
function calculateWeightedSum(multiplier, ...numbers) {
let sum = 0;
for (const num of numbers) {
sum += num * multiplier;
}
return sum;
}
const weightedResult = calculateWeightedSum(1.5, 10, 20, 30);
console.log("加权计算结果:", weightedResult); // (10 + 20 + 30) * 1.5 = 90
五、综合实战案例:变量、循环与函数协同处理数据
在真实的业务开发中,变量、循环与函数并不是孤立存在的,而是相互配合以完成复杂的数据加工任务。下面我们通过一个学生成绩综合评估系统,展示三者的协同协作方式:使用函数封装业务,内部通过变量追踪指标状态,结合循环完成过滤、汇总与分类统计。
完整可运行实战代码
/**
* 学生成绩综合分析函数
* @param {Array<{name: string, score: number}>} studentList 学生记录集合
* @param {number} passScore 及格基准线,默认为 60
* @returns {object} 包含总览数据与分类名单的分析报告
*/
function analyzeClassScores(studentList, passScore = 60) {
// 1. 边界检查:防御性编程,确保传入数据为有效非空数组
if (!Array.isArray(studentList) || studentList.length === 0) {
return {
success: false,
message: "输入学生列表无效或为空",
summary: null
};
}
// 2. 状态变量初始化
let accumulatedScore = 0;
let topStudent = studentList[0];
const passedStudents = [];
const failedStudents = [];
// 3. 循环遍历每名学生的成绩数据
for (const student of studentList) {
// 过滤异常缺失值
if (typeof student.score !== "number" || isNaN(student.score)) {
console.warn(`检测到学生 ${student.name} 的成绩数据无效,跳过统计`);
continue;
}
accumulatedScore += student.score;
// 比对并更新最高分获得者
if (student.score > topStudent.score) {
topStudent = student;
}
// 根据条件分流至不同分类数组
if (student.score >= passScore) {
passedStudents.push(student);
} else {
failedStudents.push(student);
}
}
// 4. 计算综合指标并封装结构化对象返回
const totalCount = studentList.length;
const averageScore = Number((accumulatedScore / totalCount).toFixed(2));
const passRate = ((passedStudents.length / totalCount) * 100).toFixed(1) + "%";
return {
success: true,
summary: {
totalCount,
averageScore,
passRate,
topStudentName: topStudent.name,
topScore: topStudent.score,
passedCount: passedStudents.length,
failedCount: failedStudents.length
},
passedStudents,
failedStudents
};
}
// --- 测试验证案例 ---
const mockData = [
{ name: "赵云", score: 95 },
{ name: "关羽", score: 88 },
{ name: "张飞", score: 56 },
{ name: "黄忠", score: 78 },
{ name: "魏延", score: 45 }
];
const report = analyzeClassScores(mockData, 60);
console.log("【班级成绩评估分析报告】");
console.log("总人数:", report.summary.totalCount);
console.log("平均分:", report.summary.averageScore);
console.log("及格率:", report.summary.passRate);
console.log("最高分学生:", report.summary.topStudentName, "分数:", report.summary.topScore);
console.log("未能及格人员名单:", report.failedStudents.map(s => s.name).join("、"));
六、常见初学者错误与排查指南
在掌握变量、循环与函数的使用过程中,以下几类高频问题值得特别注意:
- ReferenceError: ... is not defined(未定义引用异常):
原因通常是在大括号
{}之外尝试读取使用let或const声明的局部变量;或者在声明语句之前提前访问处于暂存死区(TDZ)的变量。排查时应检查变量作用域层级及声明位置。 - TypeError: Assignment to constant variable(常量赋值异常):
对使用
const声明的变量执行了二次赋值操作。如果变量的值需要动态改变(如递增计数器、循环累加器),应明确将其改为let声明。 - 无限死循环导致宿主进程卡死(Infinite Loop):
在
while或for循环中,若遗漏了递增语句(例如忘记写i++),或者退出判定条件永远无法变为false,循环将一直占用主线程。排查时需首先核对循环步进语句是否能有效推进状态。 - 函数缺少 return 导致默认返回 undefined:
在 JavaScript 中,如果一个函数内部执行完毕且未显式书写
return,该函数调用的求值结果将自动为undefined。在需要产出计算结果的场景下,务必检查返回路径是否完整。
console.log("调试追踪:", 变量名),打印变量的实时类型与数值,观察状态在每一步是否符合设计要求。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。