2013-09-27 113 views
5

我使用D3.js並且經常發現自己動態構建transform屬性(或在path元素上的d屬性)。這兩個通常都需要多個以逗號分隔的數字。Javascript串聯字符串

var x = 0, 
y = 1, 
path = 'M0,0 L' + [x, y]; 

有時我通過手動添加逗號建立我的琴絃:

var x = 0, 
y = 1, 
path = 'M0,0 L' + x + ',' + y; 

我已經決定,我應該嘗試

有時我通過連接數組字符串建立我的琴絃堅持一種方法或另一種方法,並且想知道哪種方法更好。

這裏有幾件事情我已經考慮:

  • 我知道打電話join()比手工串接逗號慢,但是,當它加到一個數組爲字符串的瀏覽器做什麼?
  • 第二種格式將適用於任何瀏覽器。是否有任何瀏覽器不支持第一種格式?
  • 第一種格式使用較少的字符(保持較低的文件大小始終是一個加號)。
  • 就我個人而言,我相信第一種格式更具可讀性。

是否有一種方法明顯比另一種更好?還是我只是nitpicky?

+1

你只是吹毛求疵:-)我就選擇了一個更具可讀性(在我看來,這是第二個)。 – bfavaretto

回答

9

當JavaScript將數組強制轉換爲字符串時,它實際上在數組上調用:.join(',')。所以你實際上會用.join(',')手動獲得更好的性能,而不是讓它留給解釋器來注意你強制陣列。因此:x + ',' + y是最快的,[x, y].join(',')是最好的做法(因爲它可以更容易地修改行爲),而[x, y]比手動調用.join稍微慢一點,並且有時可能無法讀取,但更方便。

+0

'.join(',')'的好處。我沒有想到這個選擇。 – Towler

+0

我很驚訝地發現'x +','+ y'實際上有多快。在我的情況下,它比'[x,y]'快4倍。 (http://www.jsfiddle.net/8VqEP) – Towler

4

簡短的回答:使用array.join。

長回答:

首先,串聯是不是比使用array.join(),它的速度較慢。這是因爲每次連接時都會銷燬兩個字符串並創建一個新字符串。

採取以下代碼:

<script> 
function concat(){ 
var txt = ''; 
for (var i = 0; i < 1000000; i++){ 
txt =+ i + ','; 
} 
} 

function arr(ar){ 
var txt = 'asdf' + ar; 
} 

ar = []; 
for (var i = 0; i < 1000000; i++) { 
ar.push(i); 
} 

concat(); 

arr(ar); 

alert('done!'); 
</script> 

並將其粘貼到一個HTML文件。然後配置它。在我的機器上(核心i7EE,16GB RAM,SSD磁盤,IE9),arr()需要0ms,concat()需要12ms。請記住,這是超過一百萬次的迭代(這個測試在IE6上會非常不同,concat()會花費幾秒鐘)。

其次,如果只有兩個值,串聯將與array.join相同。因此,就您的示例而言,從性能角度來看,它們都是等價的。如果你採用上面的代碼並將1000000更改爲4,那麼concat和arr都需要0ms執行。這意味着您的特定流量的差異不存在,或者可忽略不計,因此不會顯示在配置文件中。

第三,現代瀏覽器中使用array.join()反正優化字符串連接,這樣的討論可能從性能上看沒有實際意義。

這使得我們的風格。就我個人而言,我不會使用第一種形式,因爲我不喜歡手動連接字符串(當你有2個變量時,它非常簡單,但如果你有10個變量,那會產生一長串代碼。而如果你收到一個有n個值的數組,則會出現一個for循環)。我不會使用第二種形式,因爲正如在另一個答案中指出的那樣,這個值被強制爲一個字符串,這意味着一些隱式轉換正在進行。這裏的問題是隱含的部分。我知道現在陣列在被強制時加入了一個逗號,但是如果規範改變會發生什麼,或者一些天才決定在您的代碼庫中更改Array.prototype的toString實現?只是爲了好玩在jsfiddle中運行這個:

Array.prototype.toString = function() { 
return 'not the expected result!'; 
} 

alert([1, 2]); 

你能猜出答案是什麼嗎? (上面的代碼將通過toString()方法執行相同種類轉換爲陣列代碼脅迫。)

如果使用array.join(「」);您將通過以下方式來保護您的代碼:1)無論toString實現如何,您的數組都將被連接,並且2)它將以逗號連接。

+0

我同意你關於隱式轉換的觀點 - 這是我沒有想到的。然而,我不同意你的表現測試。我在一行代碼中構建我的字符串,而不是循環迭代。一個更好的測試案例會是這樣的(參見這個小提琴http://jsfiddle.net/8VqEP/)。你會在這裏看到TenorB的答案中的表現評分是準確的。 – Towler

+0

測試點是要表明,任何差別可以忽略不計(12毫秒是幾乎沒有),並說明如何字符串拼接速度較慢大字符串時是(1000000次迭代使一個很長的字符串)。你的小提琴比較連接一個數組與連接一個非常小的字符串。稍微修改一下(你在每次迭代中構建數組,因爲我們在分析連接而不是對象創建時會污染測試),我回到第二點。我的時間是502,2和91,對於最慢的測試,每次迭代約爲0.000502ms。微不足道。 –

+0

,使我們回到我的文章的意圖。因爲性能可以忽略不計,所以您應該使用array.join,因爲上述原因 –