news 2026/4/16 19:52:59

JavaScript学习笔记:3.控制流与错误处理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaScript学习笔记:3.控制流与错误处理

JavaScript学习笔记:3.控制流与错误处理

上一篇搞定了JS的“内功心法”(基础语法与数据类型),这一篇咱们来解锁JS的“实战技能”——控制流与错误处理。如果说变量和数据类型是JS的“砖瓦”,那控制流就是“建筑图纸”(决定代码执行顺序),错误处理就是“安全网”(防止代码崩掉)。今天就用接地气的例子,带你吃透这些核心知识点,从此写代码能“做对决策”,还能“从容兜底”~

一、块语句:给代码划清“独立空间”

块语句是JS里最基础的“代码容器”,用一对{}把多条语句包起来,就像给代码划了个“独立房间”。它通常和控制流语句(if、for、while)搭配使用,比如:

while(奶茶没喝完){吸一口;// 这整个{}就是块语句}

但这个“房间”对不同变量的“约束力”不一样——这就是新手最容易踩的坑!

避坑重点:var vs let/const的“房间规则”

  • var:串门的“邻居”:用var声明的变量不受块语句约束,会“串门”到函数或全局作用域。比如:

    var奶茶="全糖";{var奶茶="三分糖";// 同一个变量,覆盖了外面的值}console.log(奶茶);// 输出“三分糖”——var直接“串门”改了全局变量

    这就像你在自己房间换了衣服,结果邻居的衣服也跟着变了,离谱!

  • let/const:安分守己的“住户”:用let或const声明的变量是“块级作用域”,只在自己的“房间”里生效,不会打扰外面:

    let奶茶="全糖";{let奶茶="三分糖";// 独立的局部变量}console.log(奶茶);// 输出“全糖”——外面的变量不受影响

    这才是正常的“房间规则”!所以记住:块语句里优先用let/const,彻底和var说再见

二、条件语句:JS的“决策大脑”

条件语句让JS能“根据情况做选择”,就像你出门前看天气:下雨带伞,晴天戴帽。JS里有两种核心条件语句:if...elseswitch,各有擅长场景。

1. if…else:灵活的“多岔路口”

if...else就像人生的“岔路口”,满足条件走一条路,不满足走另一条。语法很简单:

if(条件A){A;}elseif(条件B){B;}else{实在没路走,兜底方案;}

但这里藏着两个“致命坑”,新手必栽!

坑1:假值的“伪装术”

JS里有6个“假值”,它们会被条件语句当成false处理,其余全是true

  • falseundefinednull
  • 0NaN
  • 空字符串""

举个反例,你以为能判断“用户输入了内容”,结果栽了:

const用户名="";// 用户没输入,是空字符串if(用户名){console.log("欢迎登录");}else{console.log("请输入用户名");// 正确执行,因为""是假值}// 坑!如果用户输入0:const年龄=0;// 0是合法年龄,但却是假值if(年龄){console.log("年龄合法");}else{console.log("请输入合法年龄");// 错误执行!}

避坑指南:如果要判断“是否存在值”,别直接用if(变量),要用精准判断:

if(年龄!==undefined&&年龄!==null){// 排除未定义和空值console.log("年龄合法");}
坑2:条件里的“赋值陷阱”

千万别在if条件里写赋值语句(=),要写比较语句(===)!比如:

let喜欢奶茶=false;if(喜欢奶茶=true){// 这里是赋值,不是比较!console.log("给你买奶茶");// 会执行,因为赋值后喜欢奶茶变成true}

这就像你本来不喜欢奶茶,别人硬塞给你一杯,然后说“你看你喜欢吧”——逻辑完全混乱!最佳实践:条件里只写比较表达式,赋值单独写。

2. switch:高效的“多选一菜单”

当有多个固定选项需要匹配时,switch比if…else更简洁,就像餐厅里的“套餐菜单”,选一个套餐就对应一套服务。语法:

switch(套餐类型){case"汉堡套餐":给汉堡;break;// 关键!选完就退出case"披萨套餐":给披萨;break;default:给默认小吃;// 没有匹配项时的兜底}
核心坑:switch的“穿透效应”

如果忘记写break,JS会继续执行下一个case的代码,就像你点了汉堡套餐,服务员不仅给了汉堡,还自动加了披萨和小吃——完全超出预期!比如:

const水果="香蕉";switch(水果){case"香蕉":console.log("香蕉是$0.48一磅");// 没写break!case"樱桃":console.log("樱桃是$3.00一磅");break;}// 输出:香蕉是$0.48一磅 → 樱桃是$3.00一磅(穿透了!)

避坑指南:除了故意利用穿透的场景(极少),每个case后面必须加break!另外,switch的匹配是严格相等(===),不会自动类型转换,比如case "1"case 1是两个不同的匹配项。

三、异常处理:JS的“安全网”——与bug和平共处

写代码难免遇到bug(就像走路难免摔跤),异常处理就是给代码装“安全网”,让它摔得轻一点,甚至能爬起来继续走。JS的异常处理核心是try...catch...finally,再加上throw自定义错误。

1. 三兄弟分工:try→尝试,catch→补救,finally→兜底

这三个语句的关系就像“快递签收流程”:

  • try:尝试做一件事(比如签收快递)
  • catch:如果出问题(快递损坏、丢件),就补救
  • finally:不管成没成功(签没签收),必须做的事(比如关门、谢谢快递员)

举个完整例子:

function签收快递(快递状态){if(快递状态==="损坏"){thrownewError("快递损坏,无法签收");// 主动抛出错误(丢件了!)}return"签收成功";}try{// 尝试签收const结果=签收快递("损坏");console.log(结果);}catch(错误){// 出问题了,补救console.error("出错了:",错误.message);// 输出错误信息联系商家理赔();// 补救措施}finally{// 不管怎样都要做console.log("快递处理完毕,关门");// 必执行!}

输出结果:

出错了:快递损坏,无法签收 快递处理完毕,关门

2. throw:主动“喊救命”——自定义错误

throw就像你发现快递有问题时,主动喊“快递员,这里有问题!”。它可以抛出任意类型的值(字符串、数字、对象),但最佳实践是抛出Error对象,因为它自带name(错误类型)和message(错误信息),方便调试:

// 不推荐:抛出字符串throw"快递损坏";// 推荐:抛出Error对象thrownewError("快递损坏,无法签收");// name: "Error", message: "快递损坏..."

还可以用更具体的错误类型,比如TypeError(类型错误)、RangeError(范围错误),让错误信息更精准:

function计算年龄(出生年份){if(typeof出生年份!=="number"){thrownewTypeError("出生年份必须是数字");// 类型错误}if(出生年份<1900||出生年份>2024){thrownewRangeError("出生年份范围必须是1900-2024");// 范围错误}return2024-出生年份;}

3. finally的“霸道逻辑”:覆盖一切返回值

finally有个很“霸道”的特性:不管try或catch里有没有return,finally都会执行,而且如果finally里有return,会直接覆盖前面的返回值!比如:

function测试(){try{return"try的返回值";}catch(e){return"catch的返回值";}finally{return"finally的返回值";// 覆盖前面的返回值}}console.log(测试());// 输出:finally的返回值

这就像你本来想签收快递(return try的结果),但最后不管怎样,都必须执行“关门”(finally的return),直接忽略了之前的想法。避坑指南:finally里尽量不要写return,它的核心用途是“释放资源”(比如关闭文件、断开网络连接),而不是返回值。

4. 错误处理的“避坑红线”

  • 别“吞掉”错误:catch块里不要只写console.log(e),要用console.error(e)(会格式化错误,方便调试),更不要空catch(catch(){}, 相当于把bug藏起来,永远找不到)。
  • 精准捕获:不要用try包裹所有代码,只包裹“可能出错的部分”(比如网络请求、数据解析),否则会掩盖真正的问题。
  • 释放资源:文件、网络连接、定时器等资源,一定要放在finally里释放,避免内存泄漏。

四、总结:控制流与错误处理的“核心心法”

  1. 块语句:用{}划清作用域,let/const是块级作用域,var是“串门户”,坚决不用var。
  2. 条件语句:
    • if…else:警惕假值陷阱,条件里不写赋值,复杂判断用块语句。
    • switch:每个case必加break,用default兜底,匹配是严格相等。
  3. 异常处理:
    • try:包裹可能出错的代码,不滥用。
    • catch:精准处理错误,不吞错,用Error对象。
    • finally:释放资源,不写return。

JS的控制流让代码“有逻辑、会决策”,错误处理让代码“抗造、不脆断”。这两个技能结合起来,你写的代码就从“勉强能跑”变成“稳健可靠”了~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 10:44:15

EtherCAT 逐帧解析状态机切换过程(初始清零阶段)

第一阶段总结&#xff1a;主站通过一系列广播写&#xff08;BWR&#xff09; 和广播读&#xff08;BRD&#xff09; 操作&#xff0c;完成从站通信基础配置与状态校准。下面逐帧解析初始化报文&#xff1a; 1、BWR 报文向地址101&#xff08;对应 DL control 寄存器&#xff09…

作者头像 李华
网站建设 2026/4/16 13:51:41

如何快速搭建专业的学术个人主页:AcadHomepage完整指南

如何快速搭建专业的学术个人主页&#xff1a;AcadHomepage完整指南 【免费下载链接】acad-homepage.github.io AcadHomepage: A Modern and Responsive Academic Personal Homepage 项目地址: https://gitcode.com/gh_mirrors/ac/acad-homepage.github.io 作为一名学者或…

作者头像 李华
网站建设 2026/4/16 10:37:40

高频IO服务优化实战指南

文章目录高频IO服务优化实战指南Netty、Reactor模型JVM消耗、零拷贝与IO线程调度深度解析&#x1f4cb; 目录⚡ 一、高频IO服务的挑战与特征&#x1f4a1; 高频IO服务特征分析&#x1f3af; 高频IO性能指标&#x1f527; 二、Netty与Reactor模型的JVM消耗分析&#x1f4a1; Net…

作者头像 李华
网站建设 2026/4/16 10:46:46

IEC61131-3工业自动化编程:5大核心语言全面解析与实战指南

IEC61131-3工业自动化编程&#xff1a;5大核心语言全面解析与实战指南 【免费下载链接】IEC61131-3编程语言及应用基础 IEC61131-3编程语言及应用基础 项目地址: https://gitcode.com/Open-source-documentation-tutorial/44794 在工业自动化快速发展的今天&#xff0c;…

作者头像 李华
网站建设 2026/4/16 7:00:09

Graphic:Flutter数据可视化的终极指南 - 从语法理论到图表实战

Graphic&#xff1a;Flutter数据可视化的终极指南 - 从语法理论到图表实战 【免费下载链接】graphic A grammar of data visualization and Flutter charting library. 项目地址: https://gitcode.com/gh_mirrors/gr/graphic Graphic是一个基于Flutter的开源数据可视化库…

作者头像 李华
网站建设 2026/4/16 10:39:51

施耐德BMEH586040S:高效节能型高性能过程变频驱动平台

产品定位 施耐德电气BMEH586040S是Altivar Process系列中的一款高效节能型高性能模块化变频器&#xff0c;专为对能效、可靠性与系统集成有严苛要求的连续过程工业及关键基础设施设计。该平台集卓越的电机控制、尖端的能源管理功能与开放的数字化连接于一体&#xff0c;是实现核…

作者头像 李华