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

如何使用函数式风格实现JavaScript数组z-order插入

实现数组z序无突变插入的简洁方案

需求说明

需要实现数组元素插入逻辑,支持两种插入规则:

  • 遵循插入顺序,直接将元素追加到数组末尾
  • 按元素的z属性升序排列插入(适配2D图形z-order绘制层级场景,要求z值相等时新元素插入到同z值元素的末尾,保证同层级后插入元素的绘制优先级)

原有命令式实现存在反向遍历、手动跳出循环、手动修正索引、拼接逻辑冗余的问题,需要更简洁的函数式无突变实现。

核心实现思路

不需要反向遍历,直接利用现有数组本身已按z值从大到小排序的特性(符合绘制顺序存储逻辑:z值越大越晚绘制,层级越高):

  1. 用findIndex正向查找第一个z值小于待插入元素z值的索引,该位置就是正确插入点:
    • 若待插入元素z值比所有元素都大,会匹配到索引0,插入到数组最开头
    • 若待插入元素z值和部分元素相等,同z元素的z值不满足「小于待插入z」的匹配条件,不会中断查找,最终插入点会落在所有同z元素之后
    • 若所有元素z值都大于等于待插入元素z值,findIndex返回-1,直接追加到数组末尾即可
  2. 无突变插入优先使用ES2023原生提供的toSpliced()方法,该方法不会修改原数组,直接返回修改后的新数组,替代手动slice+展开运算符的冗余写法。

完整实现代码

const children = [
  { z: 10 }, { z: 10 }, { z: 0 }, { z: 0 }, { z: -1 }, { z: -1 }
]

/**
 * 无突变插入元素
 * @param {object} item 待插入元素
 * @param {Array} list 原元素数组(已按z值从大到小排序)
 * @param {boolean} sortByZ 是否按z序插入,传false则直接追加到末尾
 * @returns {Array} 插入后的新数组
 */
function insert(item, list, sortByZ = true) {
  // 不按z序时直接追加
  if (!sortByZ) return [...list, item]

  // 定位插入点
  const insertIndex = list.findIndex(el => el.z < item.z)
  
  // 所有元素z都大于等于当前元素,追加到末尾
  if (insertIndex === -1) return [...list, item]

  // 原生无突变插入方法,兼容环境不支持时可替换为slice+展开运算符的写法
  return list.toSpliced(insertIndex, 0, item)
}

// 测试用例
const testCases = [
  { z: 7, name: 'new guy' },   // 插入到z=10元素后,z=0元素前
  { z: 10, name: 'new guy' },  // 插入到原有z=10元素后,z=0元素前
  { z: -1, name: 'new guy' },  // 插入到数组末尾
  { z: 90, name: 'new guy' }   // 插入到数组开头
]

testCases.forEach(testItem => {
  console.log(insert(testItem, children))
})

旧环境兼容写法

如果运行环境不支持toSpliced,可以将插入逻辑替换为以下写法,效果完全一致:

return [
  ...list.slice(0, insertIndex),
  item,
  ...list.slice(insertIndex)
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 21:09:34