如何基于frozenEdge属性对对象数组排序且兼容多浏览器
问题原因
原有代码跨浏览器不兼容的核心原因有两个:
Array.sort()稳定排序的要求是ES2019才加入ECMAScript规范的,Chrome、Safari的旧版本实现中,当比较函数返回0时,两个元素不会保留原数组中的相对顺序,而Firefox较早实现了稳定排序,因此原有代码仅在Firefox运行正常- 原有比较函数的判断逻辑存在分支漏洞,没有覆盖
frozenEdge属性所有组合的场景,进一步放大了不同浏览器排序实现的差异
全浏览器兼容解决方案
实现思路:预先记录所有元素的原始索引,给每个元素设置明确的排序权重,避免比较函数大量返回0的场景,完全不依赖浏览器的默认稳定排序特性,同时保证无效项、同优先级有效项的相对位置和原数组完全一致。
完整实现代码:
function isValidColumn(column) { return column.hasOwnProperty('field'); } const originalArray = [ {"style": "width: 10px; text-align: center","className": "oj-sm-only-hide table","headerClassName": "Sample"}, {"headerText": "Fee Description","field": "Description"}, {"headerText": "Amount","field": "FeeAmount","frozenEdge": "start"}, {"headerText": "Currency","field": "CurrencyCode","frozenEdge": "start"}, {"headerText": "Status","field": "FeeStatus"}, {"headerText": "Department","field": "DepartmentDescription"}, {"headerText": "Assessed Date","field": "AssessedDate","frozenEdge": "end"}, {"headerText": "Payment Date","field": "PaymentDate"}, {"headerText": "Paid By","field": "PaidBy","frozenEdge": "end"}, {"headerText": "Invoice","field": "Invoice"}, {"headerClassName": "table-header table-row-botton","className": "table-row-botton"} ]; const sortedArray = originalArray // 给每个元素绑定原始索引 .map((item, index) => ({ item, originalIndex: index })) .sort((a, b) => { const aIsValid = isValidColumn(a.item); const bIsValid = isValidColumn(b.item); // 任意元素为无效项,按原始索引排序,保证位置不变 if (!aIsValid || !bIsValid) { return a.originalIndex - b.originalIndex; } // 定义排序权重:start优先级最高(权重最小),end优先级最低(权重最大) const getSortWeight = (item) => { if (item.frozenEdge === 'start') return -1; if (item.frozenEdge === 'end') return 1; return 0; }; const weightDiff = getSortWeight(a.item) - getSortWeight(b.item); // 权重不同按权重排序,权重相同按原始索引排序,保留原有相对顺序 return weightDiff !== 0 ? weightDiff : a.originalIndex - b.originalIndex; }) // 提取排序后的原元素 .map(({ item }) => item); console.log(sortedArray);
该方案完全符合预期排序规则,兼容Chrome、Safari、Firefox所有主流浏览器版本。
内容的提问来源于stack exchange,提问作者shrikant5
相关产品推荐
相关产品推荐

