2013-02-01 28 views
1

當我們調用d3的可重用組件對象?

var xAxis = d3.svg.axis() 

是我們實例化一個新的軸對象?我知道axis組件是作爲閉包來實現的,但如果它也是一個對象,我很困惑。

我的問題也適用於Mike的文章Towards Reusable Charts,特別是this section的末尾。用他的模式,如果我們這樣做

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

myChart對象?如果不是,那是什麼?做這個和做什麼之間有什麼區別var myChart = new chart();

+0

由於Javascript函數也是對象,所以組件也是對象。和功能。 –

+0

但是,它們只是「對象」對象,還是它們還是「圖表」對象?即相當於調用'new chart()'? –

+1

就我所知,兩者是等同的,是的。他們是什麼類型的對象取決於你的定義:)如果你使用'instanceof'操作符,例如他們會是例如'chart'對象,但是Javascript只有一個「類」的弱概念。 –

回答

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(它也是Object)的新實例,因爲每次調用都會聲明一次myFunc

所以我們已經確定函數也是一個對象。而且,當一個函數返回另一個函數時,就好像它正在返回一個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() {}以上定義會做的實際繪製的元素裏面的一些SVG東西所有的工作,匹配'.x_axis'選擇器。

+0

哦,就像Lars說的那樣,調用'new d3.svg.axis()'會(就我所知而言)與跳過'new'相同,但僅僅因爲'axis'在功能。 – meetamit

+0

太棒了。非常感謝你的回覆。後續問:我傾向於將JS對象視爲{}容器。也就是說,如果我鍵入'console.log(object)',我會看到'Object'這個詞,然後我可以展開它,它會顯示所有的道具/方法。當我爲這個軸或者可重複使用的圖表等做這些時,我只是得到一個函數。現在,我明白函數是對象(就像數組等一樣),但爲什麼會有所不同呢?除了其他的道具/方法之外,爲什麼我們沒有看到「對象」,然後展開它並查看函數? –

+0

我認爲這只是Chrome DevTools(或螢火蟲等)的一個「功能」。在幕後,'console.log'必須檢查它正在檢查的東西的類型。也許它使用'typeof foo =='function「'或'foo instanceof Function',如果實例是按照上面描述的方式創建的,那麼它的計算結果爲'true',在這種情況下,它決定打印出函數的主體而不是其屬性。在我的Chrome版本中,通過將實例包裝在一個通用對象中:「console.log({myObj:d3.svg.axis()})',可以」欺騙「它以對象格式進行打印。 – meetamit