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

D3 v6正常运行的scaleBand在v7失效,咨询版本差异或操作问题

D3 v6与v7中scaleBand处理数组类型定义域键的行为差异

v6.7.0中的正常表现

在D3 v6.7.0中,以下代码的两个测试用例均能正常返回对应刻度值:

const range = [0, 828.156];
const domain = [[300,1],[300,2],[300,3],[400,1],[400,2],[400,3],[400,4]]
const scale = d3.scaleBand()
  .domain(domain)
  .range(range);

// test 1: 调用domain中的原数组实例,正常生效
const a = domain[3];
console.log('array a', a);
console.log('scaled a:', scale(a));

// test 2: 声明内容相同的新数组,同样正常生效
const b = [400, 1];
console.log('array b', b);
console.log('scaled b:', scale(b));

引入的D3脚本:

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js" integrity="sha512-cd6CHE+XWDQ33ElJqsi0MdNte3S+bQY819f7p3NUHgwQQLXSKjE4cPZTeGNI+vaxZynk1wVU3hoHmow3m089wA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

v7.9.0中的异常表现

升级到D3 v7.9.0后,测试2无法返回预期刻度值(输出undefined),测试1仍正常:

const range = [0, 828.156];
const domain = [[300,1],[300,2],[300,3],[400,1],[400,2],[400,3],[400,4]]

const scale = d3.scaleBand()
  .domain(domain)
  .range(range);

// test 1: 调用domain中的原数组实例,正常生效
const a = domain[3];
console.log('array a', a);
console.log('scaled a:', scale(a));

// test 2: 声明内容相同的新数组,无法匹配到刻度值
const b = [400, 1];
console.log('array b', b);
console.log('scaled b:', scale(b));

引入的D3脚本:

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js" integrity="sha512-vc58qvvBdrDR4etbxMdlTt4GBQk1qjvyORR2nrsPsFPyrs+/u5c3+1Ct6upOgdZoIl7eq6k3a1UPDSNAQi/32A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

原因说明

这是D3从v6到v7的有意版本变更,并非你的操作错误:

  • 在v6中,scaleBand内部对数组类型的定义域键采用了值序列化比较(类似将数组转为字符串后匹配),因此内容相同的不同数组实例会被视为同一个键。
  • 在v7中,scaleBand改用原生Map存储键值映射,Map的键比较遵循SameValueZero规则:对于引用类型(如数组),只有当两个引用指向同一个对象实例时才会被判定为相等。因此新声明的[400,1]和domain中的原数组是不同实例,无法匹配。

解决方案

推荐以下两种简单可行的方案:

  1. 使用原始类型作为定义域键:将数组转换为字符串或其他原始值,比如把[300,1]转为"300-1",确保内容相同的键会被视为同一值:
    const domain = ["300-1", "300-2", "300-3", "400-1", ...];
    // 查询时同样使用对应字符串
    const b = "400-1";
    console.log('scaled b:', scale(b));
    
  2. 复用定义域中的原数组实例:如果必须使用数组作为键,确保查询时使用的是domain中的原数组引用,而非新创建的数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 19:53:12