Masukkan Password
65 Tipe string JavaScript vs Objek String: Bagaimana Tipe Primitif Memiliki Metode?
Lecture ini membahas konsep yang cukup penting tetapi agak membingungkan di awal, yaitu:
Kalau
Stringadalah primitive, kenapa kita bisa melakukan"hello".toUpperCase()padahal method sepertitoUpperCase()sebenarnya berada padaString object?
Kuncinya adalah konsep boxing dan unboxing.
1. Masalah utama yang ingin dijelaskan lecture
Kita sudah belajar bahwa String termasuk primitive data type:
let str = "hello world";
Nilai "hello world" di atas adalah primitive string.
Kita juga sudah belajar berbagai method String:
str.toUpperCase();
str.toLowerCase();
str.includes("hello");
str.slice(0, 5);
str.indexOf("world");
str.replace("hello", "hi");
Nah, muncul pertanyaan:
Bukankah primitive tidak punya method?
Ini pertanyaan yang sangat bagus.
Karena secara konsep, primitive itu bukan object.
Misalnya:
let age = 20;
20 adalah primitive Number.
Tapi kita bisa melakukan:
age.toString();
Begitu juga:
let name = "John";
name.toUpperCase();
Padahal "John" adalah primitive.
Bagaimana JavaScript bisa melakukan itu?
Jawabannya:
JavaScript secara otomatis membuat temporary wrapper object ketika kita mencoba menggunakan method pada primitive.
Proses inilah yang disebut boxing.
2. Primitive String vs String Object
Ada dua cara utama yang perlu kita bedakan.
Cara pertama: String primitive
let str = "hello";
Ini menghasilkan:
"hello"
yang merupakan primitive string.
Cara kedua: String object
Kita bisa menggunakan constructor String:
let str2 = new String("hello");
Hasilnya adalah:
String object
Bukan primitive.
Secara sederhana:
let str = "hello";
↓
Primitive String
let str2 = new String("hello");
↓
String Object
3. Kenapa new String() menghasilkan object?
Coba perhatikan:
let str = "hello";
let str2 = new String("hello");
console.log(typeof str);
console.log(typeof str2);
Hasilnya:
string
object
Jadi:
| Kode | Tipe |
|---|---|
"hello" | string primitive |
new String("hello") | object |
Ini sangat penting.
4. String object memiliki property dan method
String object memiliki berbagai method seperti:
toUpperCase()
toLowerCase()
slice()
substring()
includes()
indexOf()
replace()
repeat()
concat()
dan property seperti:
length
Misalnya:
let str2 = new String("hello");
console.log(str2.length);
Hasil:
5
Karena object tersebut memiliki property length.
5. Tapi primitive juga bisa menggunakan method!
Sekarang bagian paling penting.
Kita punya:
let str = "hello";
Ini primitive.
Tetapi kita bisa:
console.log(str.toUpperCase());
Hasil:
HELLO
Padahal secara konsep toUpperCase() adalah method yang tersedia melalui wrapper/prototype String.
Jadi…
JavaScript melakukan sesuatu secara otomatis di belakang layar.
6. Apa itu Boxing?
Boxing adalah proses ketika JavaScript membungkus primitive value menjadi temporary object agar primitive tersebut bisa diperlakukan seperti object untuk sementara.
Bayangkan seperti ini.
Kamu punya:
Primitive String
"hello"
Lalu JavaScript mengatakan:
“Oh, kamu mau menggunakan method String? Sebentar, saya bungkus dulu.”
Kemudian kira-kira menjadi:
"hello"
↓
[String Object: "hello"]
↓
gunakan method
Itulah boxing.
7. Analogi sederhana: bungkus makanan 🍱
Bayangkan kamu punya makanan tanpa wadah:
🍚
Kamu ingin membawanya ke tempat lain.
Maka kamu masukkan ke wadah:
┌─────────────┐
│ 🍚 │
└─────────────┘
Setelah selesai digunakan, wadahnya tidak perlu kamu simpan.
Kamu hanya mengambil makanannya.
Dalam JavaScript:
Primitive
↓
dibungkus
↓
Wrapper Object
↓
method digunakan
↓
hasil diperoleh
↓
wrapper sementara tidak diperlukan
Primitive = makanan Object = wadah
8. Contoh konkret toUpperCase()
Kita menulis:
let str = "hello";
let upperStr = str.toUpperCase();
Kita melihatnya hanya seperti satu operasi.
Tetapi secara konsep, JavaScript melakukan sesuatu seperti:
str = "hello"
↓
primitive String
↓
boxing
↓
temporary String object
↓
toUpperCase()
↓
"HELLO"
↓
hasil dikembalikan
Jadi kita tidak perlu melakukan:
new String(...)
secara manual.
JavaScript mengurusnya untuk kita.
9. Langkah-langkahnya
Mari kita pecah lebih detail.
Kode:
let str = "hello";
let upperStr = str.toUpperCase();
Step 1 — str adalah primitive
str
isinya:
"hello"
Tipe:
string
Step 2 — JavaScript membutuhkan object wrapper
Karena kita meminta:
str.toUpperCase()
JavaScript secara internal melakukan konsep seperti:
new String(str)
sehingga sementara menjadi:
String Object
┌──────────────┐
│ "hello" │
│ length: 5 │
│ methods... │
└──────────────┘
Step 3 — Method dipanggil
Kemudian:
toUpperCase()
dijalankan pada wrapper object tersebut.
Hasilnya:
"HELLO"
Step 4 — Hasil dikembalikan
Hasil akhirnya kita simpan:
let upperStr = "HELLO";
Jadi:
console.log(upperStr);
hasilnya:
HELLO
10. Apa itu Unboxing?
Kalau:
Boxing = primitive → object
maka:
Unboxing = object wrapper → primitive value
Secara sederhana:
Primitive
↓
BOXING
↓
Object
↓
method
↓
UNBOXING
↓
Primitive result
Namun ada satu koreksi teknis kecil terhadap penjelasan lecture:
Lecture menggambarkan hasil method seolah-olah toUpperCase() menghasilkan String object lalu dilakukan .valueOf() untuk menjadi primitive.
Untuk pemahaman beginner, tidak masalah memakai gambaran tersebut.
Tetapi secara spesifikasi JavaScript, String.prototype.toUpperCase() mengembalikan primitive String, bukan String object.
Jadi gambaran yang lebih tepat:
"hello" ← primitive
↓
temporary wrapper ← boxing
↓
toUpperCase()
↓
"HELLO" ← primitive result
Ini justru membuat konsepnya lebih sederhana.
11. Kenapa wrapper object hanya sementara?
Misalnya:
let str = "hello";
str.toUpperCase();
Kita tidak perlu menyimpan object wrapper tersebut.
JavaScript hanya membutuhkannya untuk membantu menjalankan operasi.
Secara mental model:
"hello"
↓
buat wrapper sementara
↓
jalankan toUpperCase()
↓
dapat "HELLO"
↓
wrapper selesai digunakan
Object sementara tersebut nantinya bisa dibersihkan oleh garbage collector jika sudah tidak diperlukan.
12. Ini juga menjelaskan method String lainnya
Bukan hanya:
toUpperCase()
Hal yang sama berlaku ketika kita melakukan:
let str = "Hello World";
str.toLowerCase();
str.includes("Hello");
str.slice(0, 5);
str.indexOf("World");
str.replace("World", "JavaScript");
str.repeat(2);
Misalnya:
"Hello World".includes("World");
Secara mental model:
"Hello World"
↓
primitive
↓
boxing sementara
↓
String object
↓
includes("World")
↓
true
13. Bagaimana dengan length?
Ini juga menarik.
Kita bisa:
let str = "Hello";
console.log(str.length);
Hasil:
5
Padahal str adalah primitive.
JavaScript juga memberikan perilaku seolah-olah primitive tersebut memiliki wrapper String sehingga property seperti length bisa diakses.
Jadi kita bisa membayangkan:
"Hello"
↓
akses .length
↓
JavaScript menyediakan wrapper behavior
↓
5
14. Jangan tertukar dengan new String()
Ini bagian yang sangat penting untuk pemula.
Normal
let str = "hello";
Ini:
primitive string
Dengan new
let str = new String("hello");
Ini:
String object
Perhatikan perbedaannya:
console.log(typeof "hello");
// "string"
console.log(typeof new String("hello"));
// "object"
15. Sebaiknya gunakan yang mana?
Hampir selalu:
let str = "hello";
lebih baik.
Tidak perlu:
let str = new String("hello");
Kenapa?
Karena String primitive lebih sederhana dan merupakan cara normal untuk bekerja dengan string.
new String() lebih banyak dipakai untuk pembahasan teknis/legacy dan kasus khusus.
Jadi sebagai beginner:
Gunakan
"hello", bukannew String("hello").
16. Ada konsekuensi penting dari String object
Perhatikan:
let str1 = "hello";
let str2 = "hello";
console.log(str1 === str2);
Hasil:
true
Karena keduanya primitive dengan nilai yang sama.
Tetapi:
let str1 = new String("hello");
let str2 = new String("hello");
console.log(str1 === str2);
Hasilnya:
false
Karena keduanya adalah dua object berbeda.
Secara mental:
str1 ───→ Object A
"hello"
str2 ───→ Object B
"hello"
Object-nya berbeda.
Ini salah satu alasan kenapa kita tidak perlu menggunakan new String() untuk kebutuhan normal.
17. Hubungannya dengan materi sebelumnya
Ini sebenarnya nyambung dengan beberapa materi yang sudah kamu pelajari.
Sebelumnya kita belajar:
Primitive
Number
String
Boolean
Undefined
Null
BigInt
Symbol
String:
let name = "John";
adalah primitive.
Kemudian kita belajar String methods:
name.toUpperCase();
name.slice();
name.includes();
Sekarang lecture ini menjawab pertanyaan:
“Bagaimana primitive String bisa menggunakan method?”
Jawabannya:
Primitive String
↓
automatic boxing
↓
temporary String wrapper
↓
String method
↓
hasil
18. Apakah semua primitive bisa melakukan hal seperti ini?
Konsep wrapper juga berlaku pada primitive lain.
Misalnya Number:
let age = 25;
console.log(age.toString());
age adalah primitive Number, tetapi kita bisa menggunakan method.
Boolean juga:
let isActive = true;
console.log(isActive.toString());
Jadi secara umum JavaScript menyediakan wrapper object untuk primitive tertentu seperti:
string → String
number → Number
boolean → Boolean
bigint → BigInt
symbol → Symbol
Tetapi untuk pembelajaran sekarang, fokus utama lecture adalah String.
19. Apakah primitive benar-benar “tidak punya method”?
Ini cara berpikir yang paling aman:
Secara konsep:
Primitive bukan object dan tidak memiliki method sendiri seperti object.
Tetapi JavaScript memberikan automatic boxing, sehingga kita bisa menggunakan method seolah-olah primitive tersebut adalah object.
Jadi jangan berpikir:
❌ "hello" sebenarnya adalah object.
Yang benar:
✅ "hello" tetap primitive.
JavaScript hanya membuat wrapper object sementara ketika diperlukan.
20. Diagram keseluruhan
Ini diagram yang paling penting dari lecture:
PRIMITIVE
│
│
▼
"hello"
│
│
Automatic Boxing
│
▼
┌─────────────────┐
│ String Object │
│ │
│ value: "hello" │
│ length: 5 │
│ methods... │
└─────────────────┘
│
│
toUpperCase()
│
▼
"HELLO"
│
▼
hasil akhir
21. Hubungannya dengan immutable String
Ini juga menghubungkan dengan materi sebelumnya.
Kita tahu String itu immutable.
Misalnya:
let str = "hello";
str.toUpperCase();
console.log(str);
Hasil:
hello
Kenapa?
Karena:
str.toUpperCase();
tidak mengubah str.
Method tersebut menghasilkan string baru:
let upper = str.toUpperCase();
console.log(str);
console.log(upper);
Hasil:
hello
HELLO
Jadi:
str
↓
"hello"
toUpperCase()
↓
"HELLO"
String asli tetap:
"hello"
22. Contoh lain: slice()
Misalnya:
let str = "JavaScript";
let result = str.slice(0, 4);
Mental model-nya:
"JavaScript"
↓
primitive String
↓
temporary wrapper
↓
slice(0, 4)
↓
"Java"
Original:
str
tetap:
"JavaScript"
23. Jadi sebenarnya str.method() bagaimana cara membacanya?
Kalau kamu melihat:
str.toUpperCase();
jangan berpikir:
“
strpasti object.”
Lebih tepat berpikir:
“
stradalah String primitive, dan JavaScript secara otomatis menyediakan wrapper agar String method bisa digunakan.”
Ini mental model yang bagus untuk dibawa ke materi berikutnya.
24. Boxing vs Unboxing — hafalkan tabel ini
| Konsep | Artinya |
|---|---|
| Boxing | Primitive → wrapper object |
| Unboxing | Object/wrapper → primitive |
| Wrapper object | Object yang membungkus primitive |
| Automatic boxing | JavaScript melakukannya otomatis |
| Garbage collection | Membersihkan object yang sudah tidak diperlukan |
Mental model:
BOXING
primitive
↓
object
UNBOXING
object
↓
primitive
25. Jangan samakan Boxing dengan Type Coercion biasa
Ini juga penting karena lecture menghubungkannya dengan type coercion.
Type coercion misalnya:
"10" + 5
JavaScript mengubah:
5
↓
"5"
sehingga:
"10" + "5"
↓
"105"
Itu adalah type coercion.
Sedangkan:
"hello".toUpperCase()
melibatkan:
primitive String
↓
boxing
↓
wrapper object
↓
method
Jadi konsepnya berbeda.
Ringkas:
Type coercion
→ conversion antar tipe untuk operasi tertentu
Boxing
→ primitive dibungkus menjadi object sementara
26. Satu koreksi kecil terhadap lecture
Ada beberapa bagian lecture yang sebaiknya kamu pahami dengan versi yang lebih tepat.
Lecture menggambarkan kira-kira:
let tempResult = tempString.toUpperCase();
upperStr = tempResult.valueOf();
seolah-olah:
toUpperCase()
↓
String object
↓
valueOf()
↓
primitive
Untuk memahami konsep historis wrapper, gambaran itu bisa membantu.
Tetapi dalam JavaScript modern, toUpperCase() sendiri mengembalikan primitive string.
Jadi kamu tidak perlu membayangkan bahwa:
"hello".toUpperCase()
menghasilkan String object.
Lebih tepat:
"hello"
primitive
↓
temporary wrapper untuk akses method
↓
toUpperCase()
↓
"HELLO"
primitive
27. Kenapa JavaScript dibuat seperti ini?
Tujuannya terutama convenience / kemudahan penggunaan.
Bayangkan kalau JavaScript mengharuskan kita menulis:
new String("hello").toUpperCase()
setiap kali ingin menggunakan method String.
Akan sangat merepotkan.
Dengan automatic boxing, kita cukup menulis:
"hello".toUpperCase();
atau:
let name = "john";
name.toUpperCase();
Jauh lebih nyaman.
28. Analogi kehidupan sehari-hari
Bayangkan kamu punya kartu:
Kartu nama
"John"
Kartu tersebut sendiri bukan kotak.
Tapi ketika ingin menggunakan fasilitas tertentu, sistem memasukkannya sebentar ke dalam wadah:
Primitive
"John"
↓
dibungkus sementara
↓
┌─────────────────┐
│ String Wrapper │
│ "John" │
│ methods │
└─────────────────┘
↓
gunakan method
↓
selesai
↓
hasil
Kamu sebagai programmer tidak perlu melihat proses tersebut.
JavaScript mengurusnya di belakang layar.
29. Cheat sheet lecture ini
Primitive String
let str = "hello";
typeof str
→ "string"
String Object
let str = new String("hello");
typeof str
→ "object"
Automatic Boxing
"hello".toUpperCase();
Secara mental:
primitive
↓
boxing sementara
↓
method
↓
result
String methods
"hello".toUpperCase();
"HELLO".toLowerCase();
"hello world".includes("world");
"JavaScript".slice(0, 4);
"hello".indexOf("e");
"hello".replace("hello", "hi");
Primitive tetap bisa menggunakan semuanya karena automatic boxing.
String immutable
let str = "hello";
let result = str.toUpperCase();
console.log(str); // hello
console.log(result); // HELLO
Method menghasilkan nilai baru.
30. Kesimpulan paling penting
Kalau nanti kamu lupa detail lecture ini, cukup ingat 5 hal:
1. String adalah primitive
let name = "John";
name adalah primitive String.
2. String object juga ada
let name = new String("John");
Ini menghasilkan object.
3. Primitive String tetap bisa menggunakan method
name.toUpperCase();
name.slice();
name.includes();
4. JavaScript menggunakan automatic boxing
Primitive String
↓
temporary String wrapper
↓
method digunakan
↓
hasil
Kita tidak perlu membuat wrapper sendiri.
5. String asli tidak berubah
let name = "john";
let upperName = name.toUpperCase();
console.log(name); // "john"
console.log(upperName); // "JOHN"
🧠 Mental model terakhir
Bayangkan seperti ini:
KAMU MENULIS
"hello".toUpperCase()
│
▼
"hello" adalah primitive
│
▼
JavaScript membungkus
sementara (boxing)
│
▼
String wrapper object
│
▼
jalankan toUpperCase()
│
▼
"HELLO"
│
▼
wrapper tidak diperlukan
lagi setelah operasi selesai
Jadi jawaban dari pertanyaan besar lecture ini adalah:
String tetap merupakan primitive. Kita bisa memanggil method seperti
slice(),includes(), dantoUpperCase()karena JavaScript secara otomatis melakukan boxing: primitive String dibungkus sementara menjadi String wrapper object agar method tersebut dapat digunakan. Setelah operasi selesai, kita mendapatkan hasilnya dan tidak perlu mengelola wrapper tersebut secara manual.
Dan ini sebenarnya merupakan salah satu contoh bagus bagaimana JavaScript menyembunyikan kompleksitas internal supaya kita sebagai programmer bisa menulis kode yang lebih sederhana.