d3.js - d3.IE中的selection类型检查

标签 d3.js

如何检查给定对象是否为 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明确声明:

# d3.selection() <>

[…] 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 存储库:

  1. 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;
}
  1. 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];
};

它通过检查空对象 {} 上是否存在 __proto__ 访问器属性来检查浏览器是否支持 Object.prototype.__proto__。如果浏览器支持,D3 将直接分配原型(prototype),从而使其成为 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/

相关文章:

javascript - D3.nest() 没有给我所需的数据结构

javascript - 意外的画笔过滤行为

javascript - d3 svg如何使多个圆居中

javascript - 在 D3 树中添加鼠标悬停时的文本

javascript - 按照 D3 图表中给定的下载选项将 C3 图表下载为 pdf

javascript - 以图像为节点的 D3 v4 力图

javascript - d3 : Existing elements are invisible

javascript - d3.js 奇怪的旋转行为

javascript - D3 径向树状图跳至左上角

javascript - 在 d3.js 圆圈中添加阴影效果