使用'fromCharCode' (字符长度)对Javascript数组进行映射

9
以下内容来自Chrome控制台的交互会话:
myarray
//-> [67, 65, 84]

String.fromCharCode(67)
//-> "C"

String.fromCharCode(67).length
//-> 1

String.fromCharCode(myarray[0])
//-> "C"

String.fromCharCode(myarray[0]).length
//-> 1

myarray.map(String.fromCharCode)
//-> ["C", "A", "T"]

myarray.map(String.fromCharCode)[0]
//-> "C"

myarray.map(String.fromCharCode)[0].length
//-> 3

有人能解释一下为什么最后一次操作会返回3吗?

Firefox 4也会显示“3”(fiddle - Pointy
@T.J. Crowder 这个演示确实缺乏一些解释性支持,但是尽管我一开始有所怀疑,现在已经着迷了 :-) - Pointy
3个回答

17

非常有趣的问题。

答案是:你在最后得到3的原因是fromCharCode返回一个带有与调用中参数数量相同的字符数的字符串,而map使用三个参数调用回调函数:元素的值、元素的索引和正在遍历的对象。因此,这是一个带有三个字符但不是三个可以直接显示的字符的字符串。很棘手。

具体来说,我们得到第一个参数的值为"C";第二个参数(因为我们正在查看[0])是字符0;对于将数组强制转换为数字后的字符,它将基于fromCharCode使用的规则(如Šime Vidas在下面所述,它将对其执行ToUInt16处理,这将导致其结果为0)。

例如:

> String.fromCharCode(67, 0, [67, 65, 84]).length
3

...just as with the call from map.

For clarity:

> String.fromCharCode(67, 0, [67, 65, 84]).length
3
> String.fromCharCode(67, 0, null).length
3
> String.fromCharCode(67, 0, 0, 0, 0, 0, 0).length
7

如果我们确保每次只传递一个参数,就不会出现意外效果,因此直接使用它会给我们带来一个结果,我认为大多数人不会预料到:
> [67, 65, 84].map(String.fromCharCode)
["C", "A", "T"]
> [67, 65, 84].map(String.fromCharCode)[0]
"C"
> [67, 65, 84].map(String.fromCharCode)[0].length
3

这样可以让我们得到一个更易于理解的结果:

> [67, 65, 84].map(function(value) { return String.fromCharCode(value); })
["C", "A", "T"]
> [67, 65, 84].map(function(value) { return String.fromCharCode(value); })[0]
"C"
> [67, 65, 84].map(function(value) { return String.fromCharCode(value); })[0].length
1

1
我刚开始想知道...这是那种在聚会上很酷的东西。 - Pointy
这也将是一个很好的示例应用程序,可以使用Functional JavaScript库提供的“.aritize()”实用程序来完成 :-) - Pointy
@Crowder,所以这个:[67, 65, 84].map(String.fromCharCode)[0] 将返回这个字符串:"C",然而这个却返回了 false:[67, 65, 84].map(String.fromCharCode)[0] === "C"。JavaScript 做得很好 :) - Šime Vidas
@Šime Vidas:你发现我忽略了一个细节。;-)我编辑了你的注释,谢谢。 - T.J. Crowder
@Crowder 是的,很遗憾你不能通过悬停在控制台输出上来获取详细信息,这将是一个很酷的功能。 - Šime Vidas
显示剩余3条评论

4
我不能详细阐述T.J. Crowder出色的回答,但我可以提供这个特定问题的解决方法。
与其...,不如...
myarray.map(String.fromCharCode);

使用

String.fromCharCode.apply(String, myarray).split("");

除了返回预期结果的好处外,这种方法还可在不依赖 ECMAScript 第5版的 Array.prototype.map 方法的情况下运行,因此更具兼容性。

对于大字符串,如果超过参数数量,apply 将会触发 RangeError。 - bryc

0

遇到了同样的问题并找到了这个讨论帖。如果你正在使用ES6,我提出以下解决方案:

arr.map((c)=>String.fromCharCode(c));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接