柯里化是将D3重复配置转化为可复用、累积、组合的逻辑单元,通过分步注入参数、闭包固化上下文、组合配置器提升复用性与可维护性。

柯里化不是给 D3 加一层“函数式炫技”,而是把反复出现的配置动作变成可复用、可累积、可组合的逻辑单元。尤其当项目里要维护多个图表、多种主题、不同尺寸或频繁切换交互行为时,它能明显减少重复代码和上下文重算。
把绘图流程拆成可分步注入的参数链
D3 原生没有“预设图表类型”的概念,每次调用都要传 SVG、data、config 三样东西。用柯里化封装基础绘图函数后,就能按需分步注入:
- 先固定 DOM 上下文:比如 const chart = curry(drawChart)(d3.select('#chart'))
- 再绑定默认数据源或结构:比如 const salesChart = chart(salesData)
- 最后补动态配置:比如 salesChart({ theme: 'light', width: 600 }),甚至只改一个 scale:salesChart({ yScale: d3.scaleLog() })
用闭包固化高频不变的上下文
每次渲染都查一次 d3.select、重算 margin、重建 scale,既慢又冗余。写一个工厂函数,在闭包里一次性准备好这些:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- function createChart(el, width, height) { const svg = d3.select(el); const margin = { top: 20, left: 60 }; const x = d3.scaleBand().range([0, width - margin.left - margin.right]); return curry((data, config) => { /* 复用 svg/margin/x */ }); }
- 返回的函数自带环境,后续调用不再重复初始化
- 再配合柯里化,就能实现 createChart('#chart', 800, 400)(data)({ color: '#3366cc' }) 这样的清晰链式调用
把通用功能抽成可组合的配置器
tooltip 格式、颜色映射、响应式缩放这些逻辑在多个图表中重复出现,适合做成独立的柯里化函数:
- const withTooltip = curry((formatFn, chartFn) => (data, cfg) => chartFn(data, { ...cfg, tooltip: formatFn }))
- const withColor = curry((palette, chartFn) => (data, cfg) => chartFn(data, { ...cfg, color: d3.scaleOrdinal(palette) }))
- 组合使用:const barChart = withTooltip(d3.format(',.1f'))(withColor(['#3366cc', '#dc3912'])(baseBarChart))
- 新增功能只需加一个配置器,不侵入原逻辑
注意 this 绑定与 new 调用兼容性
柯里化后的函数如果被当作构造函数调用(比如 new chart(...)),或内部依赖 this 指向 SVG 实例,需确保 curry 实现能正确保留上下文:
- 推荐用 Function.prototype.bind 或显式传入 context 参数来控制 this
- 避免在柯里化体中直接使用箭头函数,否则会丢失原始 this
- 测试是否支持 new:调用后检查实例是否拥有预期原型方法

















