JavaScript方法链与对象传递疑问:D3.bin()调用差异解惑
核心区别:d3.bin()是生成器工厂,带参调用会直接执行分箱
D3的d3.bin本质是一个生成器工厂函数,两种调用方式对应完全不同的逻辑:
无参调用(生成配置型生成器)
当你写d3.bin().domain(xScale.domain()).value(metricAccessor).thresholds(12)时,每一步调用的都是生成器的配置方法——这些方法(.domain()、.value()等)会修改生成器的内部配置,并且返回生成器本身,因此支持链式调用。最终得到的binsGenerator是一个配置好的函数,把数据集传给它(binsGenerator(dataset)),才会执行分箱并返回数组。带参调用(直接执行分箱)
当你写d3.bin(dataset)时,相当于两步操作:先创建一个默认配置的生成器,再立即用这个生成器处理dataset,直接返回分箱后的数组。
你的错误写法问题所在
你写的d3.bin(dataset).domain(...)是在分箱数组上调用.domain()方法,但数组根本没有这个方法——如果是D3的正确版本,这种写法应该会抛出TypeError: d3.bin(...).domain is not a function的错误。你说返回函数,大概率是误把d3.bin(dataset)的返回值当成了生成器,但实际上它已经是执行后的数组。
正确的链式调用姿势
如果想链式调用配置方法,必须先通过无参的d3.bin()拿到生成器,配置完成后再传入数据集:
// 方式1:链式配置后直接执行 const bins = d3.bin() .domain(xScale.domain()) .value(metricAccessor) .thresholds(12) (dataset); // 方式2:拆分写法(和《Fullstack D3》示例一致) const binsGenerator = d3.bin() .domain(xScale.domain()) .value(metricAccessor) .thresholds(12); const bins = binsGenerator(dataset);
补充:为什么文档说d3.bin()传参返回数组?
D3文档里的描述是:d3.bin(data)等价于d3.bin()(data)——也就是先创建默认生成器,再执行它处理数据,所以返回数组。这里的传参是直接触发生成器执行,而非用来配置生成器。
内容的提问来源于stack exchange,提问作者oneyellowlion

