在Observable Notebook中跨单元格设置JS类属性值的报错求助
解决Observable笔记本中类属性设置的递归错误及复用方案
错误原因:类的Setter无限递归
你写的hist_class里,setter方法名和实例属性都是test_value,当执行hist1.test_value = "test value"时,会触发setter方法,而setter内部又赋值this.test_value = newvalue,这会再次调用setter,形成无限循环导致栈溢出,出现too much recursion错误。这是JavaScript类的基础写法问题,和Observable无关。
修正类的写法
把实例属性改成私有命名(比如加下划线前缀),和setter方法名区分开,同时建议添加getter方便读取属性:
class hist_class { constructor() { this._test_value = null; // 改名避免与setter冲突 } set test_value(newvalue) { this._test_value = newvalue; } get test_value() { return this._test_value; } }
Observable单元格中的正确调用
修正类之后,另一个单元格的代码可以正常运行,Observable的单元格赋值无需额外包裹大括号(除非是异步或延迟计算场景):
test1 = { const svg = d3.create("svg") .attr("width", 100) .attr("height", 50); const hist1 = new hist_class(); hist1.test_value = "test value"; svg.append("text") .text(hist1.test_value) .attr("x", 10) .attr("y", 20); return svg.node(); }
针对多图表实例复用的替代方案
在Observable中,除了类,还有更贴合平台特性的代码复用方式:
1. 工厂函数
相比类,工厂函数更轻量化,适合快速创建独立实例:
// 单元格:直方图工厂函数 createHistogram = (config = {}) => { // 默认配置 const { width = 100, height = 50, value = null } = config; const svg = d3.create("svg") .attr("width", width) .attr("height", height); // 提供更新方法 const updateValue = (newValue) => { svg.selectAll("text").remove(); svg.append("text") .text(newValue) .attr("x", 10) .attr("y", 20); }; // 初始化值 if (value) updateValue(value); return { node: () => svg.node(), updateValue }; } // 另一个单元格创建实例 histogram1 = createHistogram({ value: "第一个直方图" }) histogram2 = createHistogram({ width: 200, value: "第二个直方图" })
2. 响应式生成器
如果需要让图表响应其他单元格的值变化,可以用Observable的生成器函数:
// 单元格:可响应的直方图 *histogram(config) { const svg = d3.create("svg") .attr("width", config.width || 100) .attr("height", config.height || 50); while (true) { svg.selectAll("text").remove(); svg.append("text") .text(config.value) .attr("x", 10) .attr("y", 20); config = yield svg.node(); } } // 另一个单元格使用,后续可随时更新 hist1 = histogram({ value: "初始值" }) // 更新方式:hist1.next({ value: "新值" })
3. 参数化复用单元格
如果已有一个基础直方图单元格,可以通过传递参数快速创建多个实例:
// 原始直方图单元格(假设名为myHistogram) myHistogram = (width = 100, height = 50, value = "") => { const svg = d3.create("svg") .attr("width", width) .attr("height", height); svg.append("text").text(value).attr("x",10).attr("y",20); return svg.node(); } // 创建多个实例 histogramA = myHistogram(100,50,"实例A") histogramB = myHistogram(200,80,"实例B")
内容的提问来源于stack exchange,提问作者user1844086
相关产品推荐
相关产品推荐

