为什么JavaScript的.sort()处理Unicode扑克牌字符时跳过花色十六进制字母却识别牌值数字?
JavaScript 数组sort()方法对扑克牌HTML字符串的排序原理说明
观察到的排序现象
对存储Unicode扑克牌HTML <span> 字符串的数组调用默认 .sort() 方法时,排序遵循两个规则:
- 优先按
<span>标签class属性内的花色名称的字母顺序排序 - 同花色下会自动按牌值从小到大排序,对应Unicode十六进制编码末尾的牌值位顺序(1=A,E=K,跳过未使用的C位)
黑桃A对应的HTML代码示例:
<span onclick='cutCards(this.outerHTML);' class='spades'>🂡</span>
核心原理解答
JavaScript默认的.sort()方法在未传入自定义比较函数时,会将所有元素转为字符串,按逐字符UTF-16编码字典序对比大小:
- 不同花色的字符串在class属性段就已经出现差异:
clubs、diamonds、hearts、spades的首字母字典序c<d<h<s,所以会先按花色名称排序,此时字符串左侧已经分出大小,后续字符不会影响排序结果。 - 同花色的字符串class段完全相同,对比会继续向后执行到Unicode实体编码段:编码前缀
ǰ、紧随的花色位(同花色下a/b/c/d固定)都完全一致,最终对比到末尾的牌值十六进制位。而十六进制字符的字典序1<2<3<4<5<6<7<8<9<a<b<d<e刚好和牌值A到K的顺序完全匹配,所以会呈现自动按牌值排序的效果。
开发建议:后续业务逻辑不要依赖默认字符串排序的巧合效果,建议给每张牌单独存储花色枚举值、牌值数字属性,排序时传入自定义比较函数,可规避后续HTML结构调整带来的排序异常问题。
开发背景说明
当前开发的是德州扑克程序,目标实现切牌不洗牌的前提下首位发牌玩家必胜的效果,使用的牌堆是数学家Jeremy Kun发现的十万余个最优牌堆之一。目前已完成点击卡牌设为切牌顶牌、对局流程展示功能,后续将开发玩家最优手牌组合计算、牌型等级判定、手牌展示、赢家宣告功能。
切牌后程序运行效果截图:
内容的提问来源于stack exchange,提问作者raydpratt
相关产品推荐
相关产品推荐

