javascript - d3 的可重用组件是对象吗?

标签 javascript d3.js

当我们打电话

var xAxis = d3.svg.axis()

我们是在实例化一个新的轴对象吗?我知道 axis 组件是作为闭包实现的,但如果它也是一个对象,我会感到困惑。

我的问题也适用于 Mike 的文章 Towards Reusable Charts,特别是 this section 的结尾.使用他的模式,如果我们做类似的事情

var myChart = chart().width(720).height(80);

myChart 是一个对象吗?如果不是,那是什么?这样做和 var myChart = new chart(); 有什么区别?

最佳答案

是的,我们每次都实例化一个新的轴对象。这个实例是一个 function,在 JavaScript 中是一等对象;意思是,您可以像这样为其分配属性:

function myFunc() {}
myFunc.foo = "bar";

myFunc();// This is possible (naturally)
console.log(myFunc.foo);// ...and this is valid too

如果将上面的代码包装在一个函数中:

function giveMeMyFunc() {
    function myFunc() {}
    return myFunc;
}

然后每次打电话

myFuncInstance = giveMeMyFunc();

你得到一个 myFunc 的新实例(它也是一个对象),因为每次调用都声明一次 myFunc

因此我们已经确定函数也是对象。而且,当一个函数返回另一个函数时,就好像它返回一个对象的新实例一样,但它也是一个函数,您仍然可以调用 myFuncInstance()

为了阐明这一点,并可能回答您的其他问题,我们可以看看 d3.svg.axis() 是如何实际实现的(从 d3 源代码中松散地摘录):

d3.svg.axis = function() {
  /* Some variables here, which essentially are instance properties (protected through closure) */
  var scale = 123;
  ...

  /* This is a function, but since JavaScript functions are first-class objects, it's essentially an instance. */
  /* Each time (the outer) `d3.svg.axis()` is called, (the inner) `axis` function is a unique – not a shared – object. */
  function axis() {
    /* This is where the work of drawing the axis takes place, but won't get
      called until the axis is used (see below). */
  }

  /* Since the inner function `axis` is also an object, the following is an instance method */
  axis.scale = function(x) {
    scale = x;// here we're setting `scale`, which is basically an instance property

    // returning `axis` – a.k.a. our instance – is what enables method chaining: myAxis.scale(5).orient("left")
    return axis;
  }

  /* More methods here, like `axis.scale` above */

  /* Last line is very important: */
  /* This is where the newly created instance is return. Remember from */
  /* above, `axis` is a function, but it's an Object too, and it has the */
  /* methods we've just applied to it. */
  return axis;
}


/* Given all that, the line below returns an instance of `axis` (the inner function),
  which has more methods applied to it. */
myAxis = d3.svg.axis();

最后,由于实例 myAxis 也是一个函数,您可以调用它。当您将轴应用于选择时,这就是 d3 所做的:

d3.select('.x_axis').call(myAxis);

D3 将调用 myAxis 函数,其函数体在上面的 function axis() {} 中定义,将完成在与 '.x_axis' 选择器匹配的元素。

关于javascript - d3 的可重用组件是对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14650134/

相关文章:

javascript - 在 D3.JS 中创建元素 block 的最佳方法是什么

javascript - d3.js:饼图布局 - 调整 Angular 以创建快门效果

javascript - User.id 未定义

javascript - 如何在 Vue.js 中的模板元素中进行字符串插值?

javascript - 在 d3 map 中选择多个路径元素

javascript - d3 - 嵌套饼图的标签放置

javascript - 在移动设备上隐藏元素

javascript - 如何在单元测试期间验证已调用某个javascript函数

javascript - bootstrap下拉菜单不下拉?

javascript - C3 js ondragend 事件