JavaScript'in yerleşik bir stringbuilder sınıfı var mı?


Yanıtlar:


320

Internet Explorer için kod yazmanız gerekiyorsa, dizi birleşimlerini kullanan bir uygulama seçtiğinizden emin olun. Dizeleri +veya +=işleciyle bitiştirmek IE'de son derece yavaştır. Bu özellikle IE6 için geçerlidir. Modern tarayıcılarda +=genellikle dizi birleşimleri kadar hızlıdır.

Ben dize birleştirme çok yapmak zorunda genellikle bir dizi doldurun ve bir dize oluşturucu sınıf kullanmayın:

var html = [];
html.push(
  "<html>",
  "<body>",
  "bla bla bla",
  "</body>",
  "</html>"
);
return html.join("");

pushYöntemlerin birden fazla argümanı kabul ettiğini unutmayın .


7
Satır içi çıktı oluşturuyorsanız veya tüm üyeler değişmezse, [foo(), "bar", "baz"].join("");çalışır.
İsimsiz

1
Muhtemelen dropbox bağlantılarının neredeyse 3 yıl boyunca çalışmasını bekleyemezken, karşılaştırmayı merak ediyorum - ve hala devam ederse.
Cornelius

1
@DaveWard, bağlantınız koptu :(
Ivan Kochurkin

Ben bu string + string + string çok daha okunabilir buluyorum
Andrew Ehrlich

12
pushBirden fazla argümanı kabul edebileceğini bilmiyordum . Öğrendiğiniz rastgele şeyler.
Carcigenicate

55

Http://jsperf.com/javascript-concat-vs-join/2 adresindeki performansı tekrar kontrol ettim . Test senaryoları alfabeyi 1000 kez birleştirir veya birleştirir.

Mevcut tarayıcılarda (FF, Opera, IE11, Chrome), "concat", "birleştirme" den yaklaşık 4-10 kat daha hızlıdır.

IE8'de her ikisi de eşit sonuçlar verir.

IE7'de "katılmak" maalesef yaklaşık 100 kat daha hızlı.


3
Bunun için teşekkürler. Bu cevap listesinde çarpılmalıdır. Ayrıca IE10'da da çok daha hızlı (bunun modern bir tarayıcı olmadığını biliyorum, ancak bunu gören herhangi bir potansiyel NMCI geliştiricisi için bahsediyorum).
James Wilson

@Andreas Testinizin Chrome'da hiçbir zaman gerçek bitiştirmeyi yapmadığı bir kod yoluna çarptığına inanıyorum çünkü dize asla okunmuyor. Bunu zorlarken bile, yürütme hızı hala çok daha hızlı: jsperf.com/yet-another-string-concat-test/1
Joseph Lennox

37

Hayır, dizeler oluşturmak için yerleşik bir destek yoktur. Bunun yerine birleştirme kullanmanız gerekir.

Elbette, dizenizin farklı bölümlerinden oluşan bir dizi oluşturabilir ve ardından join()bu diziyi çağırabilirsiniz , ancak daha sonra birleştirmenin kullandığınız JavaScript yorumlayıcısında nasıl uygulandığına bağlıdır.

str1+str2Yöntemin hızını yönteme kıyasla karşılaştırmak için bir deney yaptım array.push(str1, str2).join(). Kod basitti:

var iIterations =800000;
var d1 = (new Date()).valueOf();
str1 = "";
for (var i = 0; i<iIterations; i++)
    str1 = str1 + Math.random().toString();
var d2 = (new Date()).valueOf();
log("Time (strings): " + (d2-d1));

var d3 = (new Date()).valueOf();
arr1 = [];
for (var i = 0; i<iIterations; i++)
    arr1.push(Math.random().toString());
var str2 = arr1.join("");
var d4 = (new Date()).valueOf();
log("Time (arrays): " + (d4-d3));

Her ikisini de Windows 7 x64'te Internet Explorer 8 ve Firefox 3.5.5'te test ettim.

Başlangıçta az sayıda yinelemeyi test ettim (yüzlerce, binlerce öğe). Sonuçlar tahmin edilemezdi (bazen dize birleştirme 0 milisaniye aldı, bazen 16 milisaniye sürdü, dizi birleştirme için de aynıydı).

Sayımı 50.000'e çıkardığımda, sonuçlar farklı tarayıcılarda farklıydı - Internet Explorer'da dize birleştirmesi daha hızlı (94 milisaniye) ve katılım daha yavaştı (125 milisaniye), Firefox'ta dizi katılımı daha hızlıydı (113 milisaniye) dize birleştirme (117 milisaniye).

Sonra sayımı 500'000'e çıkardım. Şimdi array.join()oldu dizisi birleştirme daha yavaş hem tarayıcılarda: string birleştirme 937 Internet Explorer msn, Firefox'ta 1155 ms, dizi Internet Explorer 1265 katılabilir ve Firefox'ta 1207 msn idi.

Internet Explorer'da "komut dosyasının yürütülmesi çok uzun sürüyor" olmadan test edebileceğim maksimum yineleme sayısı 850.000 idi. Daha sonra Internet Explorer, dize birleştirme için 1593 ve dizi birleştirme için 2046 idi ve Firefox, dize birleştirme için 2101 ve dizi birleştirme için 2249'a sahipti.

Sonuçlar - yineleme sayısı azsa, array.join()Firefox'ta daha hızlı olabileceğinden kullanmayı deneyebilirsiniz . Sayı arttığında, string1+string2yöntem daha hızlıdır.

GÜNCELLEME

Testi Internet Explorer 6'da (Windows XP) gerçekleştirdim. Testi 100.000'den fazla yinelemede denediysem süreç hemen yanıt vermedi ve hiç bitmedi. 40.000 yinelemede sonuçlar

Time (strings): 59175 ms
Time (arrays): 220 ms

Bu, Internet Explorer 6'yı desteklemeniz gerekiyorsa, array.join()hangisinin dize birleştirmesinden çok daha hızlı olduğunu seçin .


join()ECMAScript ve afaik'in her JavaScript yorumlayıcısı tarafından uygulanmaktadır. Neden "bağımlı" olsun?
Eli Gray

NASIL uygulandığı anlamına geliyordu ... eğer bir döngüde, dizenin sürekli olarak bir kerede yaratılmaya zıt olarak eklenmesi durumunda birleştirmeyi kullanmak anlamsız olurdu
John

Evet, demek istediğim buydu. Pardon My English ;-) İki tarayıcıda hangi yöntemin ne kadar hızlı çalıştığını gösteren bir karşılaştırmanın sonuçlarını ekledim. Gördüğünüz gibi, farklı.
naivistler

2
IE6, her zaman olduğu gibi, istisnadır :)
Gordon Tucker

10
IE6'lı insanlar herşeyin gerçekten yavaş olmasına alışkınlar. Seni suçlayacaklarını sanmıyorum.
Lodewijk

8

Bu kod, birkaç değişiklikle gitmek istediğiniz rotaya benziyor.

Bunun gibi görünmek için ekleme yöntemini değiştirmek isteyeceksiniz. 0 sayısını kabul etmek ve geri dönüş yapmak için değiştirdik, thisböylece eklerinizi zincirleyebilirsiniz.

StringBuilder.prototype.append = function (value) {
    if (value || value === 0) {
        this.strings.push(value);
    }
    return this;
}

Neden sadece NaN olmayan sayıları ve boş olmayan dizeleri kabul edelim? Kişisel yöntem kabul etmeyecektir null, falseboş dizeler, undefinedya NaN.
Eli Gray

@Elijah - Geçerli dizeler ve sayılar dışında hiçbir şey kabul etmeyerek StringBuilder sınıfımı temiz tutmayı tercih ederim. Bu sadece kişisel bir tercihtir.
Gordon Tucker

5

JavaScript'in ECMAScript 6 sürümü (ECMAScript 2015 olarak da bilinir) dize değişmezlerini tanıttı .

var classType = "stringbuilder";
var q = `Does JavaScript have a built-in ${classType} class?`;

Tek tırnak işaretleri yerine ters kenelerin dizeyi kapsadığına dikkat edin.


17
Bu soruya nasıl cevap veriyor?
Peter Mortensen

Peter Mortensen, bu cevap sadece bir ip inşa etmek için başka bir yol sunuyor. Orijinal poster, ne tür dize oluşturucu işlevselliğinin istendiğini belirtmedi.
Theophilus

1
Bu soruya cevap vermiyor. Hiç.
Massimiliano Kraus

2

C # 'da böyle bir şey yapabilirsiniz

 String.Format("hello {0}, your age is {1}.",  "John",  29) 

JavaScript'te şöyle bir şey yapabilirsiniz:

 var x = "hello {0}, your age is {1}";
 x = x.replace(/\{0\}/g, "John");
 x = x.replace(/\{1\}/g, 29);

2
Ben bir dize birleştirme yerine düzenli bir ifade çalıştırmak çok şüphe olacaktır
tic

Dahası, bu korkunç bir uygulamadır. {0}Değiştirilen dize içeriyorsa kırılır {1}.
ikegami

@ikegami dize bir değişken değildir, sabittir, bu yüzden bir a priori içerir.
spor

@sports, Tüm bunları kodunuz boyunca kopyalayıp yapıştırmak daha da kötü bir fikirdir.
ikegami

Yakalanmayan grupların yerini alan 1 $ ve 2 $ olan bir astar: x..replace (/ ([\ s \ S] *?) \ {0 \} ([\ s \ S] *?) \ {1 \} / g, "$ 1Tom $ 225")
T.CK

1

İlgilenenler için, Array.join'i çağırmanın bir alternatifi:

var arrayOfStrings = ['foo', 'bar'];
var result = String.concat.apply(null, arrayOfStrings);
console.log(result);

Çıktı, beklendiği gibi, 'foobar' dizesidir. Firefox'ta, bu yaklaşım Array.join'den daha iyi performans gösterir, ancak + birleştirme ile daha iyi performans gösterir. String.concat her parçanın ayrı bir bağımsız değişken olarak belirtilmesini gerektirdiğinden, arayan, çalıştırılan JavaScript motoru tarafından uygulanan herhangi bir bağımsız değişken sayısı sınırı ile sınırlıdır. Daha fazla bilgi için Function.prototype.apply () belgesine bakın .


"String.concat" tanımsız olduğundan bu Chrome'da başarısız oluyor. Bunun yerine, '' .concat.apply ('', arrayOfStrings) kullanabilirsiniz. Ama bu hala çok yavaş bir yöntem.
Andreas

1

Bu işlevi tanımladım:

function format() {
        var args = arguments;
        if (args.length <= 1) { 
            return args;
        }
        var result = args[0];
        for (var i = 1; i < args.length; i++) {
            result = result.replace(new RegExp("\\{" + (i - 1) + "\\}", "g"), args[i]);
        }
        return result;
    }

Ve c # gibi çağrılabilir:

 var text = format("hello {0}, your age is {1}.",  "John",  29);

Sonuç:

merhaba John, yaşınız 29.


1
I like
it

2
Bu cevabın soru ile ilgisi yoktur.
Massimiliano Kraus

0

Kendimi JavaScript'te çok sayıda dize birleştirmesi yaparken bulduğumda, şablon oluşturmaya başladım. Handlebars.js, HTML ve JavaScript'i daha okunabilir tutmak için oldukça iyi çalışır. http://handlebarsjs.com


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.