当我们打电话时
var xAxis = d3.svg.axis()
我们是否实例化了一个新的轴对象?我理解axis
组件是作为闭包实现的,但如果它也是一个对象,我会感到困惑。
我的问题也适用于Mike的文章“走向可重复使用的图表”,特别是this section的结尾。使用他的模式,如果我们做类似的事情
var myChart = chart().width(720).height(80);
是myChart
一个对象?如果没有,那是什么?这样做和做var myChart = new chart();
之间的区别是什么?
答案 0 :(得分:3)
是的,我们每次都要实例化一个新的轴对象。这个实例是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
一次。
所以我们已经确定一个函数也是一个Object。并且,当一个函数返回另一个函数时,它就好像它正在返回一个Object的新实例,但它也是一个函数,你仍然可以调用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'
选择器匹配的元素中实际绘制一些SVG内容的所有工作。