2013-09-27 28 views
5

I d3.js kullanarak ve genellikle kendimi dinamik transform özelliklerini (veya path unsurları d özelliklerini) bina bulmak ediyorum. Bunların ikisi de genellikle birden çok virgülle ayrılmış sayı gerektirir.JavaScript Concatenate Dizisi dize

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

Ve bazen elle virgül ekleyerek benim dizeleri oluşturmak:

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

ben denemek gerektiğine karar verdik

Bazen dizeye bir dizi birleştirerek benim dizeleri oluşturmak Bir yönteme ya da diğerine sadık kalmak ve hangi yaklaşımın daha iyi olacağını merak ediyorum.

Burada kabul ettik birkaç şey vardır:

  • Ben join() arayarak manuel virgül birleştirerek daha yavaş olduğunu biliyorum, ama bu bir dizeye bir dizi birleştirir tarayıcının ne olduğunu?
  • İkinci biçim herhangi bir tarayıcıda çalışacaktır. İlk biçimi desteklemeyen tarayıcılar var mı?
  • ilk biçimi daha az karakter (tutarak dosya düşük boyutları her zaman artı) kullanır.
  • Şahsen, ilk biçimin daha okunabilir olduğuna inanıyorum. diğerinden daha kesin iyidir tek yön

var mı? Yoksa sadece nitpicky mi oluyorum?

+1

Sadece nitpicky davranıyorsunuz :-) Daha okunaklı olanı seçerim (ve bence bu, ikincisi). – bfavaretto

cevap

9

JavaScript bir dizeye bir dizi zorladı, aslında çağırır: dizisinde .join(','). Yani diziyi zorladığınızı fark etmek için tercümana bırakılmak yerine, .join(',') ile daha iyi performans elde edersiniz. Yani: x + ',' + y en hızlıdır, [x, y].join(',') en iyi uygulamadır (davranışı değiştirmeyi kolaylaştırdığından beri) ve [x, y], .join'u el ile aramaktan biraz daha yavaştır ve bazen okunamaz durumda olabilir, ancak bu daha uygundur.

+0

İyi bir nokta .join (',') '. Bu seçeneği düşünmedim. – Towler

+0

Gerçekten ne kadar hızlı olduğunu 'x +', '+ y' bulduğuna şaşırdım. Benim durumumda, [x, y] 'den yaklaşık 4 kat daha hızlıydı. (http://www.jsfiddle.net/8VqEP) – Towler

4

Kısa cevap: Array.join kullanın.

uzun cevap:

Öncelikle, birleştirme, bu yavaş olduğunu) (Array.join kullanmaktan daha değil hızlıdır. Bunun nedeni, her bir zaman birleştirdiğinizde iki dizeyi yok eder ve yeni bir tane oluşturur.

Aşağıdaki kodu alın:

<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> 

ve bir html dosyasına yapıştırın. Ardından profili. Makinemde (çekirdek i7EE, 16GB RAM, SSD diskleri, IE9), arr() 0 ms alır ve concat() 12 ms alır. Bunun bir milyon yinelemenin üzerinde olduğunu unutmayın (bu aynı test IE6'da oldukça farklı olacaktır, concat() saniye sürer).

İkincisi, yalnızca iki değer olduğunda, birleştirme array.join ile aynı olur. Örneğiniz için, performans açısından, ikisi de eşdeğerdir. Yukarıdaki kodu alıp 1000000'ü 4 olarak değiştirirseniz, hem concat hem de arr yürütmek için 0ms değerini alır. Bu, belirli bir akışınızdaki farkın ya hiç olmadığı kadar önemsiz ya da önemsiz olduğu anlamına gelir.Üçüncüsü, modern tarayıcılar, array.join() yöntemini kullanarak dize birleştirme işlemini optimize ederler, bu nedenle tartışma muhtemelen performans açısından anlaşılmazdır.

Bize stil bırakıyor. Şahsen ben ilk formu kullanmam çünkü dizeleri manuel olarak birleştirmekten hoşlanmıyorum (2 çeşit var olduğunda oldukça basittir, ama ya 10 çeşitiniz varsa, gerçekten çok uzun bir kod satırı olacak. Ve n değerleri olan bir dizi alırsanız, bir for döngüsü gelir). İkinci formu kullanmam, çünkü başka bir cevapta işaret edildiği gibi, değer bir dizgeye zorlanır ve bu da bazı kapalı dönüşümlerin devam ettiği anlamına gelir. Buradaki sorun örtük kısımdır. Şimdi diziler zorlandığımda bir virgülle birleştirildiğini biliyorum, ancak bu özellik değiştiğinde ne olur, ya da bazı dehalar kod tabanınızda Array.prototype uygulamasının toString uygulamasını değiştirmeye ne zaman karar verir? sadece eğlence için bu jsfiddle içinde çalıştırın:

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

alert([1, 2]); 

Cevabın ne olacağını tahmin edebilir misiniz? (yukarıdaki kod, dizinizdeki kod için aynı tür bir dönüştürme işlemini gerçekleştirecektir. Eğer array.join (',') kullanırsanız, toString() yöntemi aracılığıyla

1) dizinizin toString uygulamasından bağımsız olarak birleştirileceğini ve 2) bir virgülle birleştirileceğini belirterek kodunuzu geliştirmeye devam edersiniz.

+0

Çarpışan dönüşüme dair noktanıza katılıyorum - bu düşünmediğim bir şey. Bununla birlikte, performans testine katılmıyorum. Dizgimi tek bir satırda, yinelemeli olarak bir döngü içinde yapıyorum. Daha iyi bir test vakası bunun gibi bir şey olurdu (bu keman'a bakın http://jsfiddle.net/8VqEP/). Burada, TenorB'un cevabındaki performans puanlarının doğru olduğunu göreceksiniz. – Towler

+0

testinin amacı, herhangi bir farkın önemsiz olduğunu (12 ms'nin neredeyse hiçbir şey olmadığını) ve büyük dizelerle (1000000 yinelemenin uzun bir dizge için) ne zaman daha yavaş bir dizilim birleştirdiğini göstermektir. Keman, bir diziye katılmayı karşılaştırır ve gerçekten küçük bir dizeyi birleştirir. Biraz değiştirdikten sonra (her bir yinelemede diziyi oluşturuyordunuz, bu, nesnenin oluşturulmasını değil, birleştirme oluşturduğundan beri testi kirletebilir), ikinci noktama geri dönüyorum. zamanlarım 502, 2 ve 91 idi, en yavaş test için her bir iterasyonda yaklaşık 0.000502ms. ihmal edilebilir. –

+0

bizi gönderiimin amacına geri getiriyor. performans ihmal edilebilir olduğundan, yukarıdaki –