You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UglifyJS将if语句嵌入switch表达式的实现原理问询

UglifyJS将if语句嵌入switch表达式的原理解析

我在用UglifyJS压缩代码时,发现它把部分if语句嵌套进switch表达式的写法很特殊,查了Mozilla和W3Schools的JS文档都没找到明确说明,虽然脚本运行正常,但想搞懂这个实现的原理。

相关代码

全局变量

var today = new Date();

原始脚本

function date(date = today) {
  if (date !== today) { date = new Date(date) };
  var year = date.getFullYear().toString(),
    month = (date.getMonth() + 1).toString(),
    day = date.getDate().toString(),
    shortDay,
    longDay;

  if (month.length === 1) { month = "0" + month };
  if (day.length === 1) { day = "0" + day };
  switch (date.getDay()) {
    case 0: shortDay = 'Sun'; longDay = "Sunday"; break;
    case 1: shortDay = 'Mon'; longDay = "Monday"; break;
    case 2: shortDay = 'Tue'; longDay = "Tuesday"; break;
    case 3: shortDay = 'Wed'; longDay = "Wednesday"; break;
    case 4: shortDay = 'Thu'; longDay = "Thursday"; break;
    case 5: shortDay = 'Fri'; longDay = "Friday"; break;
    case 6: shortDay = 'Sat'; longDay = "Saturday"; break;
  };

  return {
    full: year + '-' + month + '-' + day + ' ' + shortDay,
    mmddyyyy: month + '/' + day + '/' + year,
    mmddyy: month + '/' + day + '/' + year.substring(2),
    md: (date.getMonth() + 1).toString() + '/' + date.getDate().toString(),
    year, month, day, shortDay, longDay
  };
};

可读性格式化后的UglifyJS压缩脚本

function date(date = today) {
  var shortDay, longDay,
    year = (date = date !== today ? new Date(date) : date).getFullYear().toString(),
    month = (date.getMonth() + 1).toString(),
    day = date.getDate().toString();

  switch (1 === month.length && (month = "0" + month), 1 === day.length && (day = "0" + day), date.getDay()) {
    case 0: shortDay = "Sun", longDay = "Sunday"; break;
    case 1: shortDay = "Mon", longDay = "Monday"; break;
    case 2: shortDay = "Tue", longDay = "Tuesday"; break;
    case 3: shortDay = "Wed", longDay = "Wednesday"; break;
    case 4: shortDay = "Thu", longDay = "Thursday"; break;
    case 5: shortDay = "Fri", longDay = "Friday"; break;
    case 6: shortDay = "Sat", longDay = "Saturday"
  }
  
  return {
    full: year + "-" + month + "-" + day + " " + shortDay,
    mmddyyyy: month + "/" + day + "/" + year,
    mmddyy: month + "/" + day + "/" + year.substring(2),
    md: (date.getMonth() + 1).toString() + "/" + date.getDate().toString(),
    year: year, month: month, day: day,
    shortDay: shortDay, longDay: longDay
  }
}

核心原理解析

UglifyJS的这种写法其实是利用了JavaScript的两个原生语法特性:逗号运算符和逻辑与(&&)的短路特性,没有用到任何非标准语法,所以浏览器能正常执行。

1. 逗号运算符的作用

switch括号里的表达式是:

1 === month.length && (month = "0" + month), 1 === day.length && (day = "0" + day), date.getDay()

逗号运算符的规则是:依次执行每个逗号分隔的表达式,最后返回最后一个表达式的结果。所以这段代码会按顺序做三件事:

  • 先执行1 === month.length && (month = "0" + month):如果月份长度是1,就给月份补0;
  • 再执行1 === day.length && (day = "0" + day):如果日期长度是1,就给日期补0;
  • 最后返回date.getDay()的值,作为switch的判断依据。

这和原始脚本中先执行两个if补0,再用date.getDay()做switch判断的逻辑完全一致,只是把代码合并到了switch的表达式里,减少了代码行数。

2. 逻辑与(&&)的短路特性

上面的补0逻辑用了条件 && 赋值语句的写法,这是因为逻辑与的短路特性:如果前面的条件为false,就不会执行后面的语句;如果条件为true,就执行后面的语句并返回其结果。这和原始的if(条件){赋值}逻辑完全等价,只是写法更紧凑。

3. 其他压缩点的逻辑

原始脚本中if (date !== today) { date = new Date(date) }被替换成了:

date = date !== today ? new Date(date) : date

这是用三元运算符替换了if语句,并且把这个赋值表达式嵌入到了year的赋值链中,因为赋值表达式本身会返回赋值后的结果,所以可以直接链式调用.getFullYear().toString(),同样是利用表达式的执行特性来压缩代码。

总结

UglifyJS并没有发明新语法,只是把JavaScript原生的逗号运算符、逻辑短路、表达式赋值等特性组合起来,将分散的语句合并成更紧凑的写法,从而达到代码压缩的目的。这种写法虽然看起来特殊,但完全符合JS语法规范,所以能正常运行。

内容的提问来源于stack exchange,提问作者milklizard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 16:36:07