关于javascript:如何缩短将数字转换为月份名称的开关大小写块?

How to shorten switch case block converting a number to a month name?

有没有一种方法可以用更少的行来写,但仍然容易阅读?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
var month = '';

switch(mm) {
    case '1':
        month = 'January';
        break;
    case '2':
        month = 'February';
        break;
    case '3':
        month = 'March';
        break;
    case '4':
        month = 'April';
        break;
    case '5':
        month = 'May';
        break;
    case '6':
        month = 'June';
        break;
    case '7':
        month = 'July';
        break;
    case '8':
        month = 'August';
        break;
    case '9':
        month = 'September';
        break;
    case '10':
        month = 'October';
        break;
    case '11':
        month = 'November';
        break;
    case '12':
        month = 'December';
        break;
}


定义一个数组,然后按索引获取。

1
2
3
var months = ['January', 'February', ...];

var month = months[mm - 1] || '';


那不使用数组呢:)

1
2
3
4
5
6
7
8
var objDate = new Date("10/11/2009"),
    locale ="en-us",
    month = objDate.toLocaleString(locale, { month:"long" });

console.log(month);

// or if you want the shorter date: (also possible to use"narrow" for"O"
console.log(objDate.toLocaleString(locale, { month:"short" }));

根据此答案,从david storey处获取月份名称。


试试这个:

1
2
var months = {'1': 'January', '2': 'February'}; //etc
var month = months[mm];

请注意,mm可以是整数或字符串,它仍然可以工作。

如果希望不存在的键产生空字符串''(而不是undefined),则添加此行:

1
month = (month == undefined) ? '' : month;

JSFiddle。


您可以创建一个数组并查找月份名称:

1
2
3
4
var months = ['January','February','March','April','May','June','July','August','September','October','November','December']


var month = months[mm-1] || '';

参见@cupawntae的答案,了解代码|| ''背后的合理性。


小心!

应该立即触发报警铃的是第一行:var month = '';—为什么这个变量被初始化为空字符串,而不是nullundefined?这可能只是习惯或复制/粘贴代码,但除非您确定知道这一点,否则在重构代码时忽略它是不安全的。

如果使用月份名称数组并将代码更改为var month = months[mm-1];,则会更改行为,因为对于超出范围的数字或非数字值,month将是undefined。你可能知道这没问题,但在很多情况下,这是不好的。

例如,假设您的switch在函数monthToName(mm)中,有人这样调用您的函数:

1
2
3
4
5
6
7
var monthName = monthToName(mm);

if (monthName === '') {
  alert("Please enter a valid month.");
} else {
  submitMonth(monthName);
}

现在,如果您改为使用数组并返回monthName[mm-1],调用代码将不再按预期工作,当它应该显示警告时,它将提交undefined值。我不是说这是一个好的代码,但是除非你确切地知道代码是如何被使用的,否则你不能做出假设。

或者可能是原始的初始化存在,因为下面一行的一些代码假定month始终是字符串,并执行类似于month.length的操作-这将导致异常被抛出无效的月份,并可能完全杀死调用脚本。

如果你确实了解整个环境——例如,它都是你自己的代码,没有人会使用它,而且你相信自己不会忘记你在将来的某个时候做出了改变——改变这样的行为可能是安全的,但是很快许多错误都来自于这样一种假设,即在现实生活中,你比编程防御要好得多。伊利和/或彻底记录行为。

Wasmoo的答案是正确的(编辑:许多其他答案,包括接受的答案,现在也已经被修正了)-你可以使用months[mm-1] || '',或者如果你想让它更明显地一目了然,比如:

1
2
3
4
5
6
7
8
9
var months = ['January', 'February', ...];

var month;

if (mm >= 1 && m <= 12) {
  month = months[mm - 1];
} else {
  month = ''; // empty string when not a valid month
}


为了完整起见,我想补充一下目前的答案。基本上,您可以命令break关键字并直接返回适当的值。如果值不能存储在预先计算的查找表中,则此策略非常有用。

1
2
3
4
5
6
7
8
9
10
11
function foo(mm) {
    switch(mm) {
        case '1':  return 'January';
        case '2':  return 'February';
        case '3':  return 'March';
        case '4':  return 'April';
        // [...]
        case '12': return 'December';
    }
    return '';
}

再次强调,使用查找表或日期函数更简洁,主观上更好。


您可以使用数组:

1
2
3
4
5
var months = ['January', 'February', 'March', 'April',
              'May', 'June', 'July', 'August',
              'September', 'October', 'November', 'December'];

var month = months[mm - 1] || '';

这是另一个仅使用1个变量的选项,当mm超出范围时仍应用默认值''

1
2
3
4
5
var month = ['January', 'February', 'March',
             'April', 'May', 'June', 'July',
             'August', 'September', 'October',
             'November', 'December'
            ][mm-1] || '';


可以使用条件运算符将其编写为表达式而不是开关:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var month =
  mm == 1 ? 'January' :
  mm == 2 ? 'February' :
  mm == 3 ? 'March' :
  mm == 4 ? 'April' :
  mm == 5 ? 'May' :
  mm == 6 ? 'June' :
  mm == 7 ? 'July' :
  mm == 8 ? 'August' :
  mm == 9 ? 'September' :
  mm == 10 ? 'October' :
  mm == 11 ? 'November' :
  mm == 12 ? 'December' :
  '';

如果您以前没有见过链接的条件运算符,那么一开始可能会很难阅读。将其作为表达式写入,比原始代码更容易看到一个方面;很明显,代码的目的是为变量month赋值。


根据塔伊之前的回答,我将其缩短为:

1
2
var months = ['January', 'February', ...];
var month = (mm >= 1 && mm <= 12) ? months[mm - 1] : '';

或者,是的,我很欣赏,可读性较差:

1
var month = months[mm - 1] || ''; // as mentioned further up


像@vidriduch一样,我想强调I20Y("国际化")代码在当今环境中的重要性,并建议以下简洁和强大的解决方案以及单一测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function num2month(month, locale) {
    if (month != Math.floor(month) || month < 1 || month > 12)
        return undefined;
    var objDate = new Date(Math.floor(month) +"/1/1970");
    return objDate.toLocaleString(locale, {month:"long"});
}

/* Test/demo */
for (mm = 1; mm <= 12; mm++)
    document.writeln(num2month(mm,"en") +"" +
                     num2month(mm,"ar-lb") +"<br/>");
document.writeln(num2month("x","en") +"<br/>");
document.writeln(num2month(.1,"en") +"<br/>");
document.writeln(num2month(12.5,"en" +"<br/>"));

我尽量接近原来的问题,即将数字1到12转换成月份名称,不仅针对一个特殊情况,而且在出现无效论点的情况下返回undefined,使用之前添加的一些批评和其他答案的内容。(如果需要精确匹配,从undefined''的变化是微不足道的。)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var getMonth=function(month){
   //Return string to number.
    var strMonth = ['January', 'February', 'March',
             'April', 'May', 'June', 'July',
             'August', 'September', 'October',
             'November', 'December'
            ];
    //return number to string.
    var intMonth={'January':1, 'February':2, 'March':3,
             'April':4, 'May':5, 'June':6, 'July':7,
             'August':8, 'September':9, 'October':10,
             'November':11, 'December':12
            };
    //Check type and return
    return (typeof month ==="number")?strMonth[month-1]:intMonth[month]
}

我赞成瓦斯莫的解决方案,但要这样调整:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var month = [
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
    'August',
    'September',
    'October',
    'November',
    'December'
][mm-1] || '';

它是完全相同的代码,真的,但不同的缩进,这使它更可读。