2017-01-21 51 views
3

我正在開發一個D3項目,它使用一個事件偵聽器,每隔幾毫秒就會調用一次來更新/設置屏幕上圓圈位置的動畫。爲什麼事件偵聽器回調函數只能在函數範圍內工作?

它從函數startForces()開始調用一次來激活D3的力量,我們通過它的圓圈。

當回調函數(勾號)位於startForces()範圍之外時,該函數似乎只調用一次,並且圓圈在頁面上顯示爲靜態。 (查看頂級代碼塊)

但是,當回調函數(勾號)位於startForces()的範圍內時,一切都按預期工作,圓圈顯示爲動畫。 (BOTTOM CODE CHUNK)

我想了解爲什麼JavaScript是這樣工作的。爲什麼頂級代碼無法工作,底層代碼是否工作?

TL:DR

NOT-工作代碼

var ticked = function(circles){ 
    circles.attr('cx', function(d) { return d.x }) 
    .attr('cy', function(d) { return d.y }) 
} 

var startForces = function(data, circles) { 
    simulation.nodes(data) 
    .on('tick', ticked(circles)) 
} 

=====

工作代碼

var startForces = function(data, circles) { 
     simulation.nodes(data) 
     .on('tick', ticked) 

    function ticked(){ 
     circles.attr('cx', function(d) { return d.x }) 
     .attr('cy', function(d) { return d.y }) 
    } 
    } 

爲什麼不同?

回答

6

它實際上與所有功能的位置無關。

當你這樣做:

.on('tick', ticked(circles))

您立即撥打ticked權創建on聽衆。然後,將tick的回叫分配爲ticked結果,其圈數爲undefined

當你這樣做:

.on('tick', ticked)

您指定的回調是ticked功能,這是你想要的。

+1

謝謝!包圍我的頭,但它開始有意義。 – Starcat

+1

是的,這次旅行很多人起來!請記住,'ticked(circles)'的評估值是未定義的,但'ticked'的值是函數本身。您想要將該函數分配給回調函數,而不是其返回值。 – thedayturns

+1

@Starcat只需將我的兩分錢添加到thedayturns的答案中:通常,力仿真中的「tick」函數不需要參數。但是,如果您確實需要,出於某種原因,將任何參數傳遞給它,將其包裝在一個匿名函數中:'on('tick',function(){ticked(foo)})'。 –

相關問題