如何检查给定对象是否为d3
选项?
以下代码在Chrome和Firefox中打印true
,但在Internet Explorer中打印false
:
console.log(d3.select(document.body) instanceof d3.selection)
答案 0 :(得分:6)
随着D3 v4 的发布,这个问题已经消失(changelog):
选择不再使用prototype chain injection对Array进行子类化;它们现在是普通物体,提高了性能。
API docs明确声明:
[...] 此功能也可用于测试选择(
instanceof d3.selection
)
使用新版本,以下代码在所有浏览器中实际评估为true:
d3.select() instanceof d3.selection // true in Chrome, FF, IE
对于仍然在v3上的所有人,下面的原始答案都有一个问题的分析和解决方法。
由于D3的内部工作原理,每个支持Object.prototype.__proto__
的浏览器都会打印true
,而缺少对__proto__
的支持的浏览器会打印false
。检查compatibility list显而易见的是,IE< 11将表达式评估为false
。出于这个原因,您无法使用instanceof d3.selection
来检查IE中的D3选择< 11。这是带有D3的known issue,但它已关闭,无法修复。
来自D3'的github存储库:
selection/selection.js
强> 查看d3.select()
的定义,这是您通话的切入点:
d3.select = function(node) {
// ... removed for brevity
return d3_selection([group]);
};
这最终会将调用结果返回给d3_selection()
,而d3_subclass()
又将子类d3_selectionPrototype = d3.selection.prototype
。
function d3_selection(groups) {
d3_subclass(groups, d3_selectionPrototype);
return groups;
}
core/subclass.js
强> 最后,d3.selection
的实施提供了问题的答案:
var d3_subclass = {}.__proto__?
// Until ECMAScript supports array subclassing, prototype injection works well.
function(object, prototype) {
object.__proto__ = prototype;
}:
// And if your browser doesn't support __proto__, we'll use direct extension.
function(object, prototype) {
for (var property in prototype) object[property] = prototype[property];
};
通过检查空对象Object.prototype.__proto__
上是否存在__proto__
访问者属性,它检查浏览器是否支持{}
。如果浏览器支持它,D3将直接分配原型,从而使其成为d3.selection
的实例。否则,原型的所有属性将被复制到要返回的对象,而不会明确地设置原型。在这种情况下,您的表达式将评估为false
。
由于提供了{{3}}作为扩展选择功能的方法,因此您可以通过向d3.selection
添加新属性来实施解决方法,如上所述,该属性将可以访问通过任何选择,通过原型设计或复制属性。
// Include this at the start of your script to include the
// property in any selection created afterwards.
d3.selection.prototype.isD3Selection = true;
console.log(d3.select(document.body).isD3Selection); // true in any browser