有一年,我在改一段“祖传代码”。那种代码你一眼看过去就知道:
- 注释是 2013 年写的
- 变量名叫 a1、a2、temp3
- 缩进全靠感觉
- 最关键的是——你不敢删一行
我正准备跑路的时候,突然看到这样一段代码:
我当场愣住。break 后面居然跟了个名字?
我心里一万个问号:
- break 不是只能跳出一层循环吗?
- outer 是变量?函数?咒语?
- 这玩意 JS 真的支持?
于是,我第一次认真研究了一个平时写业务根本不会用,但 JS 规范里真实存在的东西:标签语句(Labelled Statement)。
而更刺激的,还在后面。
标签语句:给代码贴个“逃生出口”的牌子
1、标签语句到底是啥?
在 JavaScript 里,你可以给一条语句贴一个“标签”,语法长这样:
labelName: statement
比如:
这里的 loop1,就是一个标签。
注意:
- 标签不是变量
- 标签不参与作用域
- 它只是一个 “定位点”
你可以把它理解成代码世界里的“紧急出口标识”。
2、标签语句到底能干嘛?
99% 的场景,只干一件事:配合 break 或 continue,跳出指定的代码块。
没有标签时的循环噩梦:
问题来了:break 只会跳出 内层循环。
如果你想在某个条件满足时,直接跳出外层循环,怎么办?
很多新手会写成这样:
能用,但很丑。
3、标签 + break:一脚油门直接出循环
这时候,标签语句就登场了:
一句话总结:break outer = 直接跳到 outer 标签后面
就像你在商场迷路了,普通 break 只能走出一家店,带标签的 break,是直接冲向最近的消防通道。
4、continue 也能配合标签用
执行逻辑是:
- 当 j === 1
- 直接跳到外层循环的下一次 i
是不是有点“邪门”?
5、我的真心话:标签语句,能不用就不用
虽然它合法、规范、JS 引擎支持,但在真实业务中:
- 可读性差
- 容易让人误解
- 很像“结构化编程之前的产物”
更推荐的替代方案:
- 抽函数 + return
- 使用 Array 方法(some / every)
- 重构循环逻辑
面试会问,项目慎用。
with 语句:JS 世界里的“黑魔法斗篷”
如果说标签语句是“冷门”,那 with 语句,就是危险品级别。
1、一个诡异但合法的 JS 写法
运行没问题。问题是:a、b 从哪来的?
2、with 语句本质:临时修改作用域链
一句话解释 with:把一个对象,强行插进当前作用域链的最前面
也就是说:
JS 引擎的查找顺序变成了:
- 先找 obj.a
- 再找外层作用域的 a
这就像什么?你在公司开会,突然把“隔壁部门的文件柜”搬进会议室, 你拿到的资料:
- 可能是你们部门的
- 也可能是隔壁部门的
- 完全看不出来
3、with 最可怕的地方:你根本不知道变量是谁的
来看这段代码:
你猜结果?答案是:
但如果 obj 里没有 a 呢?
同一段代码,行为完全不同
4、为什么 with 被 JS 官方“嫌弃”?
原因很简单,但很致命:
- 破坏可读性
- 你不知道变量来自哪里
- 静态分析几乎不可能
- 性能极差
JS 引擎无法提前确定:
- 这个变量是不是对象属性
- 要不要生成优化代码
- 直接放弃优化
- 严格模式直接禁用
直接报错:SyntaxError: Strict mode code may not include a with statement
5、with 的历史使命,其实已经结束了
早期 JS 没有:
- 解构赋值
- 模块系统
- 清晰的作用域设计
with 曾经试图解决“少写点代码”的问题。但现在:
更清晰、更安全、更可维护
标签语句 vs with 语句:一张“面试防坑表”
总结:它们像什么?
如果把 JavaScript 比作一座城市:
- 标签语句: 是写着“紧急出口”的小门,你要知道它在哪,但平时别乱走。
- with 语句: 是一件“隐身斗篷”,穿上之后,连你自己都不知道自己在哪。
END
最重要的一句话送给你:真正成熟的 JS 开发者,不是“用过多少语法”,而是“知道哪些语法不该用”。
如果你觉得这篇文章:
- 帮你补了一个 JS 冷知识
- 或者让你在面试时多了一层底气
欢迎点赞、收藏、转发给那个 “写 JS 十年,还没见过 with 的朋友”~
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!