如何检查给定对象是否为 d3
选择?
以下代码在 Chrome 和 Firefox 中打印 true
,但在 Internet Explorer 中打印 false
:
console.log(d3.select(document.body) instanceof d3.selection)
最佳答案
2017-01-17更新
随着 D3 v4 的发布,这个问题已经消失(changelog):
Selections no longer subclass Array using prototype chain injection; they are now plain objects, improving performance.
和 API docs明确声明:
[…] This function can also be used to test for selections (
instanceof d3.selection
)
使用新版本,以下代码将在所有浏览器中实际计算为真:
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<11 中检查 D3 选择。这是 known issue使用 D3,但它已关闭且不会得到修复。
分析
来自 D3 的 github 存储库:
selection/selection.js
查看 d3.select()
的定义这是您调用的入口点:
d3.select = function(node) {
// ... removed for brevity
return d3_selection([group]);
};
这最终会返回对 d3_selection()
的调用结果,这又将子类化 d3_selectionPrototype = d3.selection.prototype
。
function d3_selection(groups) {
d3_subclass(groups, d3_selectionPrototype);
return groups;
}
core/subclass.js
最后,执行d3_subclass()
提供问题的答案:
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];
};
它通过检查空对象 {} 上是否存在
。如果浏览器支持,D3 将直接分配原型(prototype),从而使其成为 __proto__
访问器属性来检查浏览器是否支持 Object.prototype.__proto__
d3.selection
的实例。否则,原型(prototype)的所有属性将被复制到要返回的对象,而无需显式设置原型(prototype)。在这种情况下,您的表达式将计算为 false
。
解决方法
因为 d3.selection
提供作为扩展选择功能的方法,您可以通过向 d3.selection
添加新属性来实现解决方法,如上所述,任何选择都可以访问该属性,无论是通过原型(prototype)设计还是通过复制属性。
// 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
关于d3.js - d3.IE中的selection类型检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33232439/