Apakah JavaScript memiliki kelas stringbuilder bawaan?

Jawaban:

320

Jika Anda harus menulis kode untuk Internet Explorer pastikan Anda memilih implementasi, yang menggunakan gabungan array. String penyambung dengan +atau +=operator sangat lambat pada IE. Ini terutama berlaku untuk IE6. Pada browser modern +=biasanya hanya secepat bergabung dengan array.

Ketika saya harus melakukan banyak penggabungan string, saya biasanya mengisi array dan tidak menggunakan kelas pembuat string:

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

Perhatikan bahwa pushmetode menerima banyak argumen.

Fabian Jakobs
sumber
7
Dan jika Anda menghasilkan inline output, atau semua anggota adalah literal, [foo(), "bar", "baz"].join("");berfungsi juga.
Anonim
1
Sementara orang mungkin tidak dapat mengharapkan tautan dropbox untuk tetap bekerja selama hampir 3 tahun, saya ingin tahu tentang perbandingannya - dan jika itu masih berlaku.
Cornelius
1
@ DaveWard, tautan Anda rusak :(
Ivan Kochurkin
Saya menemukan ini menjadi lebih mudah dibaca bahwa string + string + string
Andrew Ehrlich
12
Saya tidak tahu pushbisa menerima banyak argumen. Hal-hal acak yang Anda pelajari.
Carcigenicate
55

Saya baru saja memeriksa ulang kinerjanya di http://jsperf.com/javascript-concat-vs-join/2 . Kasing uji menggabungkan atau menggabungkan alfabet 1.000 kali.

Di peramban saat ini (FF, Opera, IE11, Chrome), "concat" sekitar 4-10 kali lebih cepat daripada "join".

Di IE8, keduanya mengembalikan hasil yang sama.

Di IE7, "bergabung" sekitar 100 kali lebih cepat sayangnya.

Andreas
sumber
3
Terima kasih untuk ini. Ini harus dijumpai dalam daftar jawaban. Ini juga jauh lebih cepat pada IE10 juga (saya tahu itu bukan browser modern tapi saya sebutkan untuk setiap pengembang NMCI potensial melihat ini).
James Wilson
@Andreas Saya yakin pengujian Anda mengenai jalur kode di Chrome yang tidak pernah melakukan penggabungan sebenarnya karena string tidak pernah dibaca. Bahkan ketika memaksakan itu, kecepatan eksekusi masih jauh lebih cepat: jsperf.com/yet-another-string-concat-test/1
Joseph Lennox
37

Tidak, tidak ada dukungan bawaan untuk membangun string. Anda harus menggunakan rangkaian sebagai gantinya.

Anda bisa, tentu saja, membuat array dari berbagai bagian string Anda dan kemudian memanggil join()array itu, tetapi kemudian tergantung pada bagaimana bergabung diimplementasikan dalam penerjemah JavaScript yang Anda gunakan.

Saya membuat percobaan untuk membandingkan kecepatan str1+str2metode versus array.push(str1, str2).join()metode. Kode itu sederhana:

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

Saya mengujinya di Internet Explorer 8 dan Firefox 3.5.5, keduanya pada Windows 7 x64.

Pada awalnya saya menguji sejumlah kecil iterasi (beberapa ratus, beberapa ribu item). Hasilnya tidak dapat diprediksi (terkadang penggabungan string membutuhkan 0 milidetik, terkadang butuh 16 milidetik, sama untuk penggabungan array).

Ketika saya meningkatkan jumlah menjadi 50.000, hasilnya berbeda di browser yang berbeda - di Internet Explorer, penggabungan string lebih cepat (94 milidetik) dan join lebih lambat (125 milidetik), sementara di Firefox join join lebih cepat (113 milidetik) daripada penggabungan string (117 milidetik).

Kemudian saya menambah jumlah menjadi 500'000. Sekarang array.join()adalah lebih lambat dari string Rangkaian di kedua browser: string concatenation adalah 937 ms di Internet Explorer, 1155 ms di Firefox, array yang bergabung 1265 di Internet Explorer, dan 1207 ms di Firefox.

Jumlah iterasi maksimum yang bisa saya uji di Internet Explorer tanpa "script terlalu lama untuk dieksekusi" adalah 850.000. Kemudian Internet Explorer adalah 1593 untuk penggabungan string dan 2046 untuk penggabungan array, dan Firefox memiliki 2101 untuk penggabungan string dan 2249 untuk penggabungan array.

Hasil - jika jumlah iterasi kecil, Anda dapat mencoba menggunakannya array.join(), karena mungkin lebih cepat di Firefox. Ketika jumlahnya meningkat, string1+string2metode ini lebih cepat.

MEMPERBARUI

Saya melakukan tes di Internet Explorer 6 (Windows XP). Proses berhenti merespons segera dan tidak pernah berakhir, jika saya mencoba tes pada lebih dari 100.000 iterasi. Pada 40.000 iterasi hasilnya

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

Ini berarti - jika Anda perlu mendukung Internet Explorer 6, pilih array.join()cara mana yang lebih cepat daripada penggabungan string.

kenaifan
sumber
join()adalah bagian dari ECMAScript dan afaik setiap penerjemah JavaScript yang mengimplementasikannya. Mengapa itu "tergantung"?
Eli Grey
maksudnya BAGAIMANA itu diimplementasikan ... jika itu diterapkan dengan cara yang, dalam satu lingkaran, string terus ditambahkan berlawanan dengan yang dibuat sekaligus, maka menggunakan join tidak ada gunanya
John
Ya, itulah yang sebenarnya saya maksudkan. Maafkan bahasa Inggris saya ;-) Saya menambahkan hasil perbandingan seberapa cepat metode mana yang bekerja di dua browser. Anda bisa lihat, ini berbeda.
naivists
2
IE6, seperti biasa, adalah pengecualian :)
Gordon Tucker
10
Orang dengan IE6 terbiasa memiliki segalanya yang sangat lambat sekalipun. Saya tidak berpikir mereka akan menyalahkan Anda.
Lodewijk
8

Kode itu terlihat seperti rute yang ingin Anda ambil dengan beberapa perubahan.

Anda ingin mengubah metode penambahan agar terlihat seperti ini. Saya telah mengubahnya untuk menerima angka 0, dan membuatnya kembali thissehingga Anda dapat menambahkan rantai Anda.

StringBuilder.prototype.append = function (value) {
    if (value || value === 0) {
        this.strings.push(value);
    }
    return this;
}
Gordon Tucker
sumber
Mengapa hanya menerima nomor non-NaN dan string tidak kosong? Metode Anda tidak akan menerima null, false, string kosong, undefinedatau NaN.
Eli Grey
@ Elia - Saya lebih suka menjaga kelas StringBuilder saya bersih dengan tidak menerima apa pun kecuali string dan angka yang valid. Itu hanya preferensi pribadi.
Gordon Tucker
5

Versi ECMAScript 6 (alias ECMAScript 2015) JavaScript memperkenalkan string literal .

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

Perhatikan bahwa tanda centang-kembali, bukan tanda kutip tunggal, melampirkan string.

Theophilus
sumber
17
Bagaimana ini menjawab pertanyaan?
Peter Mortensen
@Peter Mortensen, jawaban ini hanya memberikan cara lain untuk membangun string. Poster asli tidak menentukan jenis fungsionalitas pembuat string apa yang sedang dicari.
Theophilus
1
Ini tidak menjawab pertanyaan. Sama sekali.
Massimiliano Kraus
2

Di C # Anda dapat melakukan sesuatu seperti

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

Di JavaScript Anda bisa melakukan sesuatu seperti

 var x = "hello {0}, your age is {1}";
 x = x.replace(/\{0\}/g, "John");
 x = x.replace(/\{1\}/g, 29);
olahraga
sumber
2
Saya sangat ragu menjalankan ekspresi reguler di tempat string bergabung akan lebih performant
tic
Lebih jauh lagi, ini adalah implementasi yang mengerikan. Ini akan rusak jika string yang {0}diganti berisi {1}.
ikegami
@ikegami string bukan variabel, adalah konstanta, jadi Anda tahu apa yang terkandung apriori.
olahraga
@sports, Menyalin dan menempel semua itu di seluruh kode Anda adalah ide yang lebih buruk.
ikegami
Satu liner dengan $ 1 dan $ 2 menggantikan grup yang tidak ditangkap: x..replace (/ ([\ s \ S] *?) \ {0 \} ([\ s \ S] *?) \ {1 \} / g, "$ 1Tom $ 225")
T.CK
1

Bagi yang tertarik, berikut ini alternatif untuk memohon Array.join:

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

Output, seperti yang diharapkan, adalah string 'foobar'. Di Firefox, pendekatan ini mengungguli Array.join tetapi dikalahkan oleh + concatenation. Karena String.concat mengharuskan setiap segmen untuk ditetapkan sebagai argumen terpisah, pemanggil dibatasi oleh batas jumlah argumen yang diberlakukan oleh mesin JavaScript yang menjalankan. Lihatlah dokumentasi Function.prototype.apply () untuk informasi lebih lanjut.

Harun
sumber
Ini gagal di Chrome, karena "String.concat" tidak ditentukan. Sebagai gantinya, Anda bisa menggunakan '' .concat.apply ('', arrayOfStrings). Tetapi ini masih merupakan metode yang sangat lambat.
Andreas
1

Saya telah mendefinisikan fungsi ini:

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

Dan bisa disebut seperti c #:

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

Hasil:

halo John, usiamu 29 tahun.

TotPeRo
sumber
1
Saya suka itu ... sepertinya c #
Ayo Adesina
2
Jawaban ini tidak ada hubungannya dengan pertanyaan.
Massimiliano Kraus
0

Ketika saya menemukan diri saya melakukan banyak penggabungan string dalam JavaScript, saya mulai mencari templating. Handlebars.js berfungsi cukup baik agar HTML dan JavaScript lebih mudah dibaca. http://handlebarsjs.com

awal
sumber