我正在使用D3编写一些图表组件。其中一些组件是故意通用的,因此可以在各种场景中重复使用。
在一个函数中,我收到一个scale对象作为参数。我想采取略有不同的行动,具体取决于这是线性比例,时间尺度还是序数比例。
然而,我不能轻易地看到如何检测我所拥有的那种规模。
instanceof
不起作用 - 这些对象不是使用new
创建的,并且没有原型集。它们是添加了附加属性的Function对象。
typeof
在所有情况下(自然地)返回'对象'
至少在序数量表的情况下,我可以使用一些其他属性进行检测,所以我可以使用:
if (scale.rangeBound) {
// do something specific to ordinal scales
}
但对于不同类型的量化量表似乎并非如此,它们似乎具有相同的属性集。
我可以为我创建的每个比例添加一些属性来指示它的类型,但我不愿意,因为它会降低我正在创建的函数的通用性(它们需要传递给它们的比例,这些比例已经添加了这些属性)。此外,我还有可能与未来版本的D3添加的某些属性发生冲突。
实际上这个问题可以扩展到D3中的许多对象。有什么方法可以区分它们吗?
答案 0 :(得分:2)
我玩了一会儿,找到了可能有用的东西。我不确定这是多么可靠,但是比较所有三种尺度共享的方法的字符串版本似乎可以得到理想的结果。
声明
console.log(""+ordinal.domain);
打印函数ordinal.domain的一些表示(至少对我来说,这是源代码)。对于ordinal.domain的任何两个实例,这应该是相同的。它似乎有效,但确实感觉应该有更好的方法。
var ordinal = d3.scale.ordinal();
var ordinal2 = d3.scale.ordinal();
var time = d3.time.scale();
var range = d3.scale.linear();
ordinal.domain([1,2]);
ordinal.range([2,3])
console.log(""+ordinal.domain == ""+ordinal2.domain); //true
console.log(""+time.domain == ""+ordinal.domain); //false
console.log(""+range.domain == ""+time.domain); //false
答案 1 :(得分:2)
您可以通过编码对比例行为进行编码来对自己进行代码更改,而不是内部
function checkType(scale) {
var s = scale.copy();
if (s.domain([1, 2]).range([1, 2])(1.5) === 1)
return "ordinal";
else if (s.domain([1, 2]).range([1, 2]).invert(1.5) === 1.5)
return "linear";
else if (s.domain([1, 2]).range([1, 2]).invert(1.5) instanceof Date)
return "time";
else
return "not supported";
}
请注意,对于具有相同行为的其他/自定义比例,这仍然会绊倒。