Apakah javascript menggunakan string yang tidak dapat diubah atau berubah? Apakah saya memerlukan "pembuat string"?
Apakah javascript menggunakan string yang tidak dapat diubah atau berubah? Apakah saya memerlukan "pembuat string"?
Jawaban:
Mereka tidak berubah. Anda tidak dapat mengubah karakter dalam string dengan sesuatu seperti var myString = "abbdef"; myString[2] = 'c'
. Metode manipulasi string seperti trim
, slice
mengembalikan string baru.
Dengan cara yang sama, jika Anda memiliki dua referensi ke string yang sama, memodifikasi satu tidak mempengaruhi yang lain
let a = b = "hello";
a = a + " world";
// b is not affected
Namun, saya selalu mendengar apa yang disebutkan Ash dalam jawabannya (bahwa menggunakan Array.join lebih cepat untuk penggabungan) jadi saya ingin menguji berbagai metode merangkai string dan mengabstraksi cara tercepat menjadi StringBuilder. Saya menulis beberapa tes untuk melihat apakah ini benar (tidak!).
Ini adalah apa yang saya yakini sebagai cara tercepat, meskipun saya terus berpikir bahwa menambahkan pemanggilan metode mungkin membuatnya lebih lambat ...
function StringBuilder() {
this._array = [];
this._index = 0;
}
StringBuilder.prototype.append = function (str) {
this._array[this._index] = str;
this._index++;
}
StringBuilder.prototype.toString = function () {
return this._array.join('');
}
Berikut ini adalah tes kecepatan kinerja. Mereka bertiga menciptakan string raksasa yang terdiri dari penggabungan"Hello diggity dog"
seratus ribu kali menjadi string kosong.
Saya telah membuat tiga jenis tes
Array.push
danArray.join
Array.push
, lalu menggunakanArray.join
Kemudian saya membuat tiga tes yang sama dengan mengabstraksikannya ke dalam StringBuilderConcat
, StringBuilderArrayPush
dan StringBuilderArrayIndex
http://jsperf.com/string-concat-without-sringbuilder/5 Silakan pergi ke sana dan menjalankan tes sehingga kita bisa mendapatkan sampel yang bagus. Perhatikan bahwa saya memperbaiki bug kecil, sehingga data untuk tes dihapus, saya akan memperbarui tabel setelah ada cukup data kinerja. Pergi ke http://jsperf.com/string-concat-without-sringbuilder/5 untuk tabel data lama.
Berikut adalah beberapa angka (Pembaruan terbaru di Ma5rch 2018), jika Anda tidak ingin mengikuti tautan. Angka pada setiap tes dalam 1000 operasi / detik ( lebih tinggi lebih baik )
| Browser | Index | Push | Concat | SBIndex | SBPush | SBConcat |
---------------------------------------------------------------------------
| Chrome 71.0.3578 | 988 | 1006 | 2902 | 963 | 1008 | 2902 |
| Firefox 65 | 1979 | 1902 | 2197 | 1917 | 1873 | 1953 |
| Edge | 593 | 373 | 952 | 361 | 415 | 444 |
| Exploder 11 | 655 | 532 | 761 | 537 | 567 | 387 |
| Opera 58.0.3135 | 1135 | 1200 | 4357 | 1137 | 1188 | 4294 |
Temuan
Saat ini, semua browser evergreen menangani penggabungan string dengan baik. Array.join
hanya membantu IE 11
Secara keseluruhan, Opera tercepat, 4 kali lebih cepat dari Array.join
Firefox adalah yang kedua dan Array.join
hanya sedikit lebih lambat di FF tetapi jauh lebih lambat (3x) di Chrome.
Chrome adalah yang ketiga tetapi string concat 3 kali lebih cepat dari Array.join
Membuat StringBuilder tampaknya tidak terlalu mempengaruhi kinerja.
Semoga orang lain menemukan ini berguna
Kasus Uji yang berbeda
Karena @RoyTinker berpikir bahwa pengujian saya salah, saya membuat case baru yang tidak membuat string besar dengan menggabungkan string yang sama, menggunakan karakter yang berbeda untuk setiap iterasi. Rangkaian senar masih tampak lebih cepat atau sama cepatnya. Mari kita menjalankan tes-tes itu.
Saya menyarankan semua orang harus terus memikirkan cara lain untuk menguji ini, dan merasa bebas untuk menambahkan tautan baru ke berbagai kasus uji di bawah ini.
join
concatenation vs string, karenanya membangun array sebelum pengujian. Saya tidak berpikir itu curang jika tujuan itu dipahami (dan join
menyebutkan array secara internal, jadi tidak curang untuk menghilangkan for
loop dari join
tes, baik).
Array.join
dari buku badak :
Dalam JavaScript, string adalah objek yang tidak dapat diubah, yang berarti bahwa karakter di dalamnya tidak boleh diubah dan bahwa operasi apa pun pada string benar-benar membuat string baru. String diberikan oleh referensi, bukan oleh nilai. Secara umum, ketika suatu objek ditugaskan oleh referensi, perubahan yang dilakukan pada objek melalui satu referensi akan terlihat melalui semua referensi lain ke objek. Karena string tidak dapat diubah, Anda dapat memiliki banyak referensi ke objek string dan tidak khawatir bahwa nilai string akan berubah tanpa Anda sadari
null
undefined
number
dan boolean
. String diberikan oleh nilai dan bukan oleh referensi dan diteruskan demikian. Jadi, string bukan hanya tidak berubah, mereka adalah sebuah nilai . Mengubah string "hello"
menjadi "world"
seperti memutuskan bahwa mulai sekarang pada angka 3 adalah angka 4 ... itu tidak masuk akal.
var a = "hello";var b=a;a.x=5;console.log(a.x,b.x);
String
objek yang dibuat menggunakan konstruktor string adalah pembungkus di sekitar nilai string JavaScript. Anda dapat mengakses nilai string dari tipe kotak menggunakan .valueOf()
fungsi - ini juga berlaku untuk Number
objek dan nilai angka. Penting untuk mencatat String
objek yang dibuat menggunakan new String
bukan string aktual tetapi pembungkus atau kotak di sekitar string. Lihat es5.github.io/#x15.5.2.1 . Tentang bagaimana benda dikonversi menjadi objek, lihat es5.github.io/#x9.9
Kiat kinerja:
Jika Anda harus menggabungkan string besar, masukkan bagian string ke dalam array dan gunakan Array.Join()
metode untuk mendapatkan keseluruhan string. Ini bisa berkali-kali lebih cepat untuk menggabungkan sejumlah besar string.
Tidak ada StringBuilder
dalam JavaScript.
Hanya untuk memperjelas pikiran sederhana seperti milik saya (dari MDN ):
Immutables adalah objek yang kondisinya tidak dapat diubah setelah objek dibuat.
String dan Angka Tidak Berubah.
Abadi berarti bahwa:
Anda bisa membuat nama variabel menunjuk ke nilai baru, tetapi nilai sebelumnya masih tersimpan di memori. Karenanya perlu pengumpulan sampah.
var immutableString = "Hello";
// Dalam kode di atas, objek baru dengan nilai string dibuat.
immutableString = immutableString + "World";
// Kami sekarang menambahkan "Dunia" ke nilai yang ada.
Ini terlihat seperti kita memutasikan string 'immutableString', tapi ternyata tidak. Sebagai gantinya:
Pada menambahkan "immutableString" dengan nilai string, peristiwa berikut terjadi:
- Nilai "immutableString" yang ada diambil
- "World" ditambahkan ke nilai "immutableString" yang ada
- Nilai yang dihasilkan kemudian dialokasikan ke blok memori baru
- Objek "immutableString" sekarang menunjuk ke ruang memori yang baru dibuat
- Ruang memori yang sebelumnya dibuat sekarang tersedia untuk pengumpulan sampah.
Nilai tipe string tidak dapat diubah, tetapi objek String, yang dibuat dengan menggunakan konstruktor String (), dapat berubah, karena ini adalah objek dan Anda dapat menambahkan properti baru ke dalamnya.
> var str = new String("test")
undefined
> str
[String: 'test']
> str.newProp = "some value"
'some value'
> str
{ [String: 'test'] newProp: 'some value' }
Sementara itu, meskipun Anda bisa menambahkan properti baru, Anda tidak bisa mengubah properti yang sudah ada
Cuplikan layar tes di konsol Chrome
Kesimpulannya, 1. semua nilai tipe string (tipe primitif) tidak dapat diubah. 2. Objek String dapat berubah, tetapi nilai tipe string (tipe primitif) yang dikandungnya tidak dapat diubah.
new String
menghasilkan wrapper yang bisa berubah-ubah di sekitar string yang tidak dapat diubah
String
objek (pembungkus), yang berarti itu tidak dapat diubah (secara default; seperti objek lain yang dapat Anda panggil Object.freeze
untuk menjadikannya tidak berubah). Tetapi tipe nilai string primitif, apakah terkandung dalam String
objek wrapper atau tidak, selalu tidak berubah.
Mengenai pertanyaan Anda (dalam komentar Anda untuk tanggapan Ash) tentang StringBuilder di ASP.NET Ajax, para ahli tampaknya tidak setuju dengan yang satu ini.
Christian Wenz mengatakan dalam bukunya Programming ASP.NET AJAX (O'Reilly) bahwa "pendekatan ini tidak memiliki efek yang terukur pada memori (pada kenyataannya, implementasi tampaknya lebih cepat daripada pendekatan standar)."
Di sisi lain Gallo dkk mengatakan dalam buku mereka ASP.NET AJAX in Action (Manning) bahwa "Ketika jumlah string untuk digabungkan lebih besar, pembuat string menjadi objek penting untuk menghindari penurunan kinerja besar."
Saya kira Anda perlu melakukan pembandingan sendiri dan hasilnya mungkin berbeda di antara peramban juga. Namun, bahkan jika itu tidak meningkatkan kinerja, itu mungkin masih dianggap "berguna" untuk programmer yang digunakan untuk pengkodean dengan StringBuilders dalam bahasa seperti C # atau Java.
Ini posting yang terlambat, tetapi saya tidak menemukan kutipan buku yang bagus di antara jawaban.
Inilah yang pasti kecuali dari buku yang dapat diandalkan:
String tidak dapat diubah dalam ECMAScript, artinya setelah dibuat, nilainya tidak dapat berubah. Untuk mengubah string yang dipegang oleh suatu variabel, string asli harus dihancurkan dan variabel diisi dengan string lain yang berisi nilai baru ... —Profesional JavaScript untuk Pengembang Web, 3rd Ed., Hal.43
Sekarang, jawaban yang mengutip kutipan buku Badak itu benar tentang kekekalan string tetapi salah mengatakan "String diberikan oleh referensi, bukan oleh nilai." (mungkin mereka awalnya bermaksud menempatkan kata-kata dengan cara yang berlawanan).
Kesalahpahaman "referensi / nilai" diklarifikasi dalam "JavaScript Profesional", bab bernama "Nilai-nilai Primitif dan Referensi":
Lima tipe primitif ... adalah: Tidak terdefinisi, Null, Boolean, Number, dan String. Variabel-variabel ini dikatakan diakses oleh nilai, karena Anda memanipulasi nilai aktual yang disimpan dalam variabel. —Profesional JavaScript untuk Pengembang Web, 3rd Ed., Hal.85
yang bertentangan dengan objek :
Saat Anda memanipulasi suatu objek, Anda benar-benar bekerja pada referensi ke objek itu daripada objek itu sendiri. Untuk alasan ini, nilai-nilai tersebut dikatakan diakses dengan referensi. —Profesional JavaScript untuk Pengembang Web, 3rd Ed., Hal.85
String JavaScript memang tidak dapat diubah.
String dalam Javascript tidak dapat diubah