Objek `String`

Artikel ini menjelaskan tentang objek String.

Penjelasan mencakup segala sesuatu dari dasar hingga teknik tingkat lanjut, termasuk jebakan yang berkaitan dengan Unicode dan ekspresi reguler, secara bertahap dan mudah dipahami.

YouTube Video

Objek String

String di JavaScript adalah salah satu tipe yang paling sering digunakan dalam pengembangan sehari-hari.

Perbedaan Antara String Primitif dan Objek String

String primitif (seperti "hello") berperilaku berbeda dengan objek pembungkus seperti new String("hello"). Biasanya, Anda harus menggunakan tipe primitif, dan hanya sedikit kebutuhan untuk memakai bentuk objek.

1// Primitive string
2const a = "hello";
3
4// String wrapper object
5const b = new String("hello");
6
7console.log(typeof a); // "string"
8console.log(typeof b); // "object"
9console.log(a === b);  // false — wrapper objects are not strictly equal
  • Kode ini menunjukkan perbedaan tipe antara primitif dan pembungkusnya, serta bagaimana perilaku mereka dengan perbandingan ketat. Dalam kebanyakan kasus, hindari menggunakan new String() dan tetaplah menggunakan primitif.

Cara Membuat String (Literal dan Template Literal)

Template literal berguna untuk memasukkan variabel dan menulis string multi-baris. Anda dapat menyisipkan variabel dan mengevaluasi ekspresi secara intuitif.

1const name = "Alice";
2const age = 30;
3
4// Template literal
5const greeting = `Name: ${name}, Age: ${age + 1}`;
6
7console.log(greeting); // "Name: Alice, Age: 31"
  • Template literal sangat mudah dibaca dan ideal untuk membangun string kompleks, termasuk string multi-baris.

Metode Umum (Pencarian dan Ekstraksi Substring)

Objek String memiliki banyak metode dasar.

 1const text = "Hello, world! Hello again.";
 2
 3// search
 4console.log(text.indexOf("Hello"));       // 0
 5console.log(text.indexOf("Hello", 1));    // 13
 6console.log(text.includes("world"));      // true
 7console.log(text.startsWith("Hello"));    // true
 8console.log(text.endsWith("again."));     // true
 9
10// slice / substring
11console.log(text.slice(7, 12));           // "world"
12console.log(text.substring(7, 12));       // "world"
  • slice dan substring serupa, tetapi mereka menangani indeks negatif dengan cara berbeda. slice menafsirkan nilai negatif sebagai posisi dari akhir. Jelaslah dalam memilih mana yang akan digunakan.

Memisahkan dan Menggabungkan (split / join)

Sudah umum untuk membagi string menjadi array untuk diproses dan kemudian digabungkan kembali.

1const csv = "red,green,blue";
2const arr = csv.split(","); // ["red","green","blue"]
3
4console.log(arr);
5console.log(arr.join(" | ")); // "red | green | blue"
  • Pola umum adalah menggunakan split untuk membagi string, memproses array hasilnya dengan map atau filter, lalu menggunakan join untuk menggabungkan kembali.

Penggantian dan Ekspresi Reguler

replace hanya mengganti kecocokan pertama. Jika Anda ingin mengganti semua kecocokan, gunakan flag g pada ekspresi reguler. Dengan memberikan fungsi sebagai pengganti, Anda juga dapat melakukan penggantian secara dinamis.

 1const s = "foo 1 foo 2";
 2
 3// replace first only
 4console.log(s.replace("foo", "bar")); // "bar 1 foo 2"
 5
 6// replace all using regex
 7console.log(s.replace(/foo/g, "bar")); // "bar 1 bar 2"
 8
 9// replace with function
10const r = s.replace(/\d+/g, (match) => String(Number(match) * 10));
11console.log(r);    // "foo 10 foo 20"
  • Dengan penggantian dinamis menggunakan fungsi, Anda dapat menulis kode yang menganalisa dan mengubah kecocokan secara ringkas.

Konversi Huruf dan Normalisasi

Untuk mendukung multibahasa dan perbandingan, selain toLowerCase dan toUpperCase, normalisasi Unicode (normalize) juga penting. Ini sangat diperlukan saat membandingkan karakter dengan aksen.

 1// Case conversion example:
 2// "\u00DF" represents the German letter "ß".
 3// In some locales, converting "ß" to uppercase becomes "SS".
 4// JavaScript follows this behavior.
 5console.log("\u00DF");
 6console.log("\u00DF".toUpperCase()); // "SS"
 7
 8// Unicode normalization example:
 9// "e\u0301" is "e" + a combining acute accent.
10// "\u00e9" is the precomposed character "é".
11// These two look the same but are different code point sequences.
12const a = "e\u0301";
13const b = "\u00e9";
14
15console.log(a === b);   // false: different underlying code points
16console.log(a.normalize() === b.normalize()); // true: normalized to the same form
  • Representasi Unicode yang berbeda, seperti ligatur dan karakter gabungan, tidak akan sama begitu saja, jadi gunakan normalize() sebelum membandingkan.

Unicode dan Titik Kode (Penanganan Surrogate Pair)

String JavaScript adalah urutan unit kode UTF-16, jadi beberapa karakter seperti emoji dapat memakan dua unit kode untuk satu karakter. Untuk menangani unit karakter sesungguhnya, gunakan Array.from, operator spread, atau for...of.

 1// Emoji composed with multiple code points:
 2// "\u{1F469}" = woman, "\u{200D}" = Zero Width Joiner (ZWJ),
 3// "\u{1F4BB}" = laptop. Combined, they form a single emoji: 👩‍💻
 4const s = "\u{1F469}\u{200D}\u{1F4BB}";
 5console.log(s);
 6
 7// Length in UTF-16 code units (not actual Unicode characters):
 8// Because this emoji uses surrogate pairs + ZWJ, the length may be > 1.
 9console.log("Length:", s.length);
10
11// Iterate by Unicode code points (ES6 for...of iterates code points):
12// Each iteration gives a full Unicode character, not UTF-16 units.
13for (const ch of s) {
14  console.log(ch);
15}
16
17// Convert to an array of Unicode characters:
18console.log(Array.from(s));
  • length mengembalikan jumlah unit kode, jadi Anda mungkin tidak mendapatkan jumlah yang diharapkan untuk emoji atau ligatur. for...of dan Array.from menangani sesuatu yang hampir seperti karakter yang ditampilkan (cluster grapheme), tetapi jika Anda membutuhkan dukungan grapheme lengkap, pertimbangkan untuk menggunakan library khusus.

Penggantian Ekspresi Reguler yang Aman (Saat Menangani Input Pengguna)

Jika Anda lupa menambahkan escape pada input pengguna saat memasukkannya ke dalam ekspresi reguler, hal ini dapat menyebabkan perilaku yang tidak terduga dan kerentanan. Selalu lakukan escape pada input pengguna sebelum menggunakannya dalam pola.

1function escapeRegex(s) {
2  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3}
4
5const userInput = "a+b";
6const pattern = new RegExp(escapeRegex(userInput), "g");
7console.log("a+b a+b".replace(pattern, "X")); // "X X"
  • Jangan gunakan string dari pengguna secara langsung pada ekspresi reguler; selalu lakukan escape sebelum membuat regex.

Tips Performa: Penggabungan dan Template

Saat menggabungkan banyak string kecil secara berurutan, memasukkannya ke dalam array dan menggunakan join dapat lebih efisien. Di sisi lain, template string sangat mudah dibaca dan cukup cepat dalam sebagian besar kasus.

 1// concatenation in loop (less ideal)
 2let s = "";
 3for (let i = 0; i < 1000; i++) {
 4  s += i + ",";
 5}
 6
 7// using array + join (often faster for many pieces)
 8const parts = [];
 9for (let i = 0; i < 1000; i++) {
10  parts.push(i + ",");
11}
12const s2 = parts.join("");
  • Mesin JavaScript modern sangat teroptimasi, jadi Anda tidak perlu khawatir tentang performa untuk jumlah penggabungan yang sedikit. Namun, jika Anda perlu menggabungkan hingga puluhan ribu kali, penggunaan join bisa lebih efisien.

Teknik Praktis yang Berguna: Padding, Trim, dan Repeat

trim, padStart, padEnd, dan repeat adalah metode yang praktis dan sangat berguna dalam pemrosesan string sehari-hari. Metode-metode tersebut sering digunakan dalam situasi praktis seperti memformat nilai input atau menstandarkan format keluaran.

1console.log("  hello  ".trim());       // "hello"
2console.log("5".padStart(3, "0"));     // "005"
3console.log("x".repeat(5));            // "xxxxx"
  • Metode-metode ini dapat digunakan untuk menormalkan input formulir atau menghasilkan output dengan lebar tetap.

Perbandingan String (Perbandingan Berdasarkan Lokal)

localeCompare efektif untuk membandingkan string berdasarkan urutan kamus untuk bahasa yang berbeda. Anda dapat menentukan opsi bahasa dan sensitivitas (seperti sensitif terhadap huruf besar/kecil).

1console.log(
2  "\u00E4".localeCompare("z", "de")
3); // may be -1 or other depending on locale
4
5console.log(
6  "a".localeCompare("A", undefined, { sensitivity: "base" })
7); // 0
  • Untuk perbandingan yang terinternasionalisasi, gunakan localeCompare dan tentukan lokal serta opsi yang tepat.

Contoh Praktis: Mengonversi Baris CSV ke Objek (Alur Kerja Praktis)

Kasus penggunaan umum adalah mengurai satu baris CSV menjadi objek dengan kombinasi split, trim, dan map. Untuk bidang yang diberi tanda kutip atau file CSV yang kompleks, gunakan parser CSV khusus.

 1// simple CSV parse (no quotes handling)
 2function parseCsvLine(line, headers) {
 3  const values = line.split(",").map(v => v.trim());
 4  const obj = {};
 5  headers.forEach((h, i) => obj[h] = values[i] ?? null);
 6  return obj;
 7}
 8
 9const headers = ["name", "age", "city"];
10const line = " Alice , 30 , New York ";
11console.log(parseCsvLine(line, headers));
12// { name: "Alice", age: "30", city: "New York" }
  • Metode ini bekerja untuk CSV sederhana, tetapi tidak bisa menangani kasus di mana koma berada di dalam bidang dengan tanda kutip.

Kesalahan Umum

Ada beberapa spesifikasi dan perilaku yang mudah terlewatkan dalam penanganan string JavaScript. Untuk menghindari bug yang tak terduga, penting untuk memperhatikan poin-poin berikut ini.

  • Menggunakan new String() dapat menghasilkan hasil yang salah dengan pemeriksaan tipe atau perbandingan. Dalam kebanyakan kasus, tipe string primitif sudah cukup.
  • Dalam Unicode, satu karakter yang terlihat dapat terdiri dari beberapa unit kode. Oleh karena itu, nilai yang dikembalikan oleh length mungkin tidak sesuai dengan jumlah karakter yang ditampilkan.
  • Saat memasukkan input pengguna ke dalam ekspresi reguler, selalu lakukan escape terlebih dahulu.
  • String.prototype.replace() secara default hanya mengganti kecocokan pertama. Jika Anda ingin mengganti semua kemunculan, gunakan flag /g dalam ekspresi reguler Anda.
  • String bersifat immutable, sehingga operasi selalu mengembalikan string baru. Penting untuk selalu menetapkan nilai yang dikembalikan.

Ringkasan

Walaupun string JavaScript terlihat sederhana, penting untuk memahami karakteristiknya terkait Unicode dan sifat immutable-nya. Dengan menguasai dasar-dasarnya, Anda dapat meningkatkan keandalan dan keterbacaan pemrosesan string Anda secara signifikan.

Anda dapat mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Silakan periksa juga saluran YouTube kami.

YouTube Video