Kelas `Object` di JavaScript
Artikel ini menjelaskan kelas Object di JavaScript.
Artikel ini menjelaskan kelas Object di JavaScript, termasuk contoh praktis.
YouTube Video
Kelas Object di JavaScript
Object adalah objek bawaan yang menjadi dasar untuk semua objek JavaScript. Banyak fitur inti bahasa, seperti manajemen properti, pewarisan (rantai prototipe), enumerasi, cloning, dan pembekuan, disediakan melalui perilaku Object.
Object.create
Ada berbagai cara untuk membuat objek, dan Anda harus menggunakannya dengan tepat sesuai tujuan Anda.
Object literal (yang paling umum)
Kode berikut menunjukkan cara paling sederhana dan mudah dibaca untuk membuat sebuah objek.
1// Create an object using object literal
2const user = {
3 name: "Alice",
4 age: 30,
5 greet() {
6 return `Hello, I'm ${this.name}`;
7 }
8};
9
10console.log(user.greet()); // "Hello, I'm Alice"
- Dalam contoh ini, properti dan metode didefinisikan menggunakan literal. Ini sederhana dan umumnya menawarkan kinerja yang unggul.
Konstruktor new Object()
Konstruktor Object jarang digunakan, tetapi berguna untuk memahami perilakunya.
1// Create an object using the Object constructor
2const objFromCtor = new Object();
3objFromCtor.x = 10;
4objFromCtor.y = 20;
5
6console.log(objFromCtor); // { x: 10, y: 20 }
new Object()mengembalikan objek kosong, namun literal{}lebih singkat dan lebih umum digunakan.
Menentukan prototipe dengan Object.create
Object.create digunakan untuk membuat objek dengan prototipe tertentu.
1// Create an object with a specified prototype
2const proto = { hello() { return "hi"; } };
3const obj = Object.create(proto);
4obj.name = "Bob";
5
6console.log(obj.hello()); // "hi"
7console.log(Object.getPrototypeOf(obj) === proto); // true
Object.createsangat ideal untuk desain objek berbasis pewarisan, memungkinkan Anda mengontrol rantai prototipe dengan presisi.
Atribut properti dan deskriptor
Properti memiliki atribut seperti 'value', 'writable', 'enumerable', dan 'configurable', yang dapat dikontrol secara rinci dengan Object.defineProperty.
Contoh dasar penggunaan defineProperty
Berikutnya adalah contoh mendefinisikan properti yang tidak dapat dienumerasi dan hanya-baca menggunakan defineProperty.
1// Define a non-enumerable read-only property
2const person = { name: "Carol" };
3
4Object.defineProperty(person, "id", {
5 value: 12345,
6 writable: false,
7 enumerable: false,
8 configurable: false
9});
10
11console.log(person.id); // 12345
12console.log(Object.keys(person)); // ["name"] — "id" is non-enumerable
13person.id = 999; // silently fails or throws in strict mode
14console.log(person.id); // still 12345
- Dengan menggunakan
defineProperty, Anda dapat mengontrol perilaku properti secara tepat seperti enumerasi, penulisan ulang, dan penghapusan.
Properti akses (getter / setter)
Dengan aksesors, Anda dapat menyisipkan logika pada saat properti dibaca dan ditulisi.
1// Use getter and setter to manage internal state
2const data = {
3 _value: 1,
4 get value() {
5 return this._value;
6 },
7 set value(v) {
8 if (typeof v === "number" && v > 0) {
9 this._value = v;
10 } else {
11 throw new Error("value must be a positive number");
12 }
13 }
14};
15
16console.log(data.value); // 1
17data.value = 5;
18console.log(data.value); // 5
19// data.value = -1; // would throw
- Dengan
getterdansetter, Anda dapat memperlakukan akses properti seperti API eksternal dan menambahkan validasi atau efek samping.
Prototipe dan pewarisan (prototype / __proto__ / Object.getPrototypeOf)
Pewarisan di JavaScript didasarkan pada rantai prototipe, bukan pada kelas. Objek dapat merujuk ke objek lain sebagai prototipe mereka.
Object.getPrototypeOf dan Object.setPrototypeOf
Contoh berikut menunjukkan cara memeriksa dan mengatur prototipe.
1// Inspect and change prototype
2const base = { speak() { return "base"; } };
3const derived = Object.create(base);
4console.log(Object.getPrototypeOf(derived) === base); // true
5
6const other = { speak() { return "other"; } };
7Object.setPrototypeOf(derived, other);
8console.log(derived.speak()); // "other"
Object.getPrototypeOfmengambil prototipe dari sebuah objek.Object.setPrototypeOfmengubah prototipe dari objek yang ada, namun harus digunakan dengan hati-hati karena dapat memengaruhi performa.
Metode bawaan yang penting
Kami akan menjelaskan dengan jelas metode yang paling sering digunakan dan penting yang dipilih dari metode instan yang disediakan oleh Object.prototype, serta metode statis yang dimiliki oleh Object.
hasOwnProperty, isPrototypeOf, toString, valueOf
hasOwnProperty, isPrototypeOf, toString, dan valueOf mendefinisikan perilaku dasar dari objek.
1// Demonstrate prototype methods
2const base = { greet() { return "hello"; } };
3const child = Object.create(base);
4const a = { x: 1 };
5
6console.log(a.hasOwnProperty("x")); // true
7console.log(a.hasOwnProperty("toString")); // false — toString is inherited
8
9console.log(a.toString()); // "[object Object]" by default
10
11console.log(base.isPrototypeOf(child)); // true
12console.log(Object.prototype.isPrototypeOf(child)); // true
hasOwnPropertyadalah metode penting untuk memeriksa apakah suatu properti ada langsung pada objek tersebut.isPrototypeOfmemeriksa apakah objek target memiliki dirinya sendiri sebagai prototipe.
Object.keys, Object.values, Object.entries
Object.keys, Object.values, dan Object.entries mengembalikan daftar properti enumerable milik objek itu sendiri. Metode-metode ini berguna untuk iterasi dan transformasi.
1// Keys, values and entries
2const item = { id: 1, name: "Widget", price: 9.99 };
3
4// ["id", "name", "price"]
5console.log(Object.keys(item));
6
7// [1, "Widget", 9.99]
8console.log(Object.values(item));
9
10// [["id",1], ["name","Widget"], ["price",9.99]]
11console.log(Object.entries(item));- Metode-metode ini sering digunakan untuk iterasi dan transformasi objek.
Object.assign
Object.assign digunakan untuk menyalin secara dangkal dan menggabungkan objek. Perlu dicatat bahwa prototipe dan properti akses tidak ikut tersalin.
1// Shallow copy / merge using Object.assign
2const target = { a: 1 };
3const source = { b: 2 };
4const result = Object.assign(target, source);
5
6console.log(result); // { a: 1, b: 2 }
7console.log(target === result); // true (merged into target)
- Untuk objek bersarang, hanya referensinya yang disalin, sehingga Anda membutuhkan implementasi berbeda untuk kloning mendalam.
Object.freeze, Object.seal, Object.preventExtensions
Object.freeze, Object.seal, dan Object.preventExtensions mengontrol mutabilitas objek.
1// Freeze vs seal vs preventExtensions
2const obj = { a: 1 };
3Object.freeze(obj);
4obj.a = 2; // fails silently or throws in strict mode
5delete obj.a; // fails
6
7const obj2 = { b: 2 };
8Object.seal(obj2);
9obj2.b = 3; // allowed
10// delete obj2.b; // fails
11
12const obj3 = { c: 3 };
13Object.preventExtensions(obj3);
14obj3.d = 4; // fails
freezeadalah yang paling ketat; metode ini mencegah segala perubahan pada properti objek.sealmencegah penambahan atau penghapusan properti, tetapi memungkinkan perubahan nilai dari properti yang sudah ada.preventExtensionshanya mencegah penambahan properti baru; properti yang sudah ada masih dapat diubah atau dihapus.
Enumerabilitas objek, urutan, dan for...in / for...of
for...in mengenumerasi nama properti enumerable, namun juga menyertakan properti pada rantai prototipe, sehingga sering digunakan bersama dengan hasOwnProperty. Menggabungkan Object.keys() dengan for...of lebih aman dan membuat tujuan Anda lebih jelas.
1// Safe enumeration
2const obj = Object.create({ inherited: true });
3obj.own = 1;
4
5for (const key in obj) {
6 if (obj.hasOwnProperty(key)) {
7 console.log("own prop:", key);
8 } else {
9 console.log("inherited prop:", key);
10 }
11}
12
13for (const key of Object.keys(obj)) {
14 console.log("key via Object.keys:", key);
15}- Aturan enumerasi properti diatur dalam spesifikasi ECMAScript, dan dalam beberapa kasus urutan enumerasi dijamin, sementara pada kasus lain tidak demikian. Sebagai aturan umum, kunci yang diinterpretasikan sebagai angka diurutkan secara menaik, sementara kunci lain mengikuti urutan penyisipan.
Kloning dan penyalinan mendalam
Ada dua jenis penyalinan objek: penyalinan dangkal menggunakan Object.assign atau sintaks spread, dan penyalinan mendalam menggunakan metode rekursif. Penting untuk menggunakannya secara tepat sesuai dengan situasi.
Salinan dangkal (spread syntax / Object.assign)
1// Shallow copy with spread operator
2const original = { a: 1, nested: { x: 10 } };
3const shallow = { ...original };
4shallow.nested.x = 99;
5console.log(original.nested.x); // 99 — nested object is shared
- Dengan salinan dangkal, objek bersarang berbagi referensi, sehingga perubahan pada objek asli dapat mempengaruhi salinannya.
Salinan mendalam sederhana (dengan peringatan)
Menggunakan trik JSON adalah cara cepat untuk membuat salinan mendalam, tetapi memiliki kekurangan seperti kehilangan fungsi, Date, referensi sirkular, dan nilai undefined. Untuk kloning mendalam yang benar, Anda perlu menggunakan pustaka khusus.
1// Deep clone using JSON methods — limited use-cases only
2const source = { a: 1, d: new Date(), nested: { x: 2 } };
3const cloned = JSON.parse(JSON.stringify(source));
4console.log(cloned); // ok for plain data, but Date becomes string, functions lost
- Metode berbasis JSON nyaman untuk menangani data sederhana dengan cepat, tetapi dalam kasus umum, perilakunya bisa tidak berjalan dengan baik.
Mixin dan komposisi objek
Alih-alih pewarisan ganda, pola komposisi perilaku menggunakan mixin sering digunakan.
1// Simple mixin function
2const canEat = {
3 eat() { return `${this.name} eats`; }
4};
5const canWalk = {
6 walk() { return `${this.name} walks`; }
7};
8
9function createPerson(name) {
10 const person = { name };
11 return Object.assign(person, canEat, canWalk);
12}
13
14const p = createPerson("Dana");
15console.log(p.eat()); // "Dana eats"
16console.log(p.walk()); // "Dana walks"
- Mixin bersifat fleksibel, tetapi Anda harus berhati-hati terhadap tabrakan nama properti dan keterujian.
Kesalahan umum dan praktik terbaik
Berikut beberapa kesalahan umum dan praktik terbaik.
-
Mutabilitas Objek secara default dapat diubah (mutable). Dalam aplikasi dengan manajemen state, pertimbangkan struktur data immutable menggunakan
Object.freezeatau pustaka immutable. -
Pencemaran prototipe Menggabungkan data eksternal langsung ke objek menggunakan
Object.assignatau loop dapat menyebabkan efek samping tak terduga pada properti khusus seperti__proto__atauconstructor, menimbulkan risiko keamanan. Saring input pengguna sebelum langsung menggabungkannya. -
Kesalahan penggunaan
for...infor...injuga mengenumerasi properti pada prototipe, jadi periksa denganhasOwnProperty. MenggunakanObject.keyslebih jelas. -
Penyalahgunaan salinan dangkal Pertimbangkan apakah Anda perlu salinan mendalam untuk mencegah perubahan pada objek bersarang memengaruhi objek asli.
Contoh Praktis: Pola Pembaruan Objek Immutable
Pola yang mengembalikan objek baru tanpa mengubah state secara langsung umum digunakan di React dan pustaka serupa.
1// Immutable update example
2const state = { todos: [{ id: 1, text: "Buy milk", done: false }] };
3
4// Toggle todo done immutably
5function toggleTodo(state, todoId) {
6 return {
7 ...state,
8 todos: state.todos.map(t => t.id === todoId ? { ...t, done: !t.done } : t)
9 };
10}
11
12const newState = toggleTodo(state, 1);
13console.log(state.todos[0].done); // false
14console.log(newState.todos[0].done); // true
- Kode ini adalah contoh membuat objek state baru tanpa langsung mengubah objek
stateyang asli. FungsitoggleTodomenyalin arraytodosdan mengembalikan objek baru dengan hanya elemen target yang dimodifikasi, sehinggastateyang asli tetap tidak berubah. - Pembaruan immutable mengurangi efek samping dan memudahkan manajemen status.
Contoh Praktis: Penggabungan Aman (Waspada Pencemaran Prototipe)
Saat menggabungkan JSON eksternal, abaikan __proto__ untuk mencegah pencemaran prototipe.
1// Safe merge ignoring __proto__ keys
2function safeMerge(target, source) {
3 for (const key of Object.keys(source)) {
4 if (key === "__proto__" || key === "constructor") continue;
5 target[key] = source[key];
6 }
7 return target;
8}
9
10const target = {};
11const source = JSON.parse('{"a":1,"__proto__":{"polluted":true}}');
12safeMerge(target, source);
13console.log(target.polluted); // undefined — safe
14console.log({}.polluted); // undefined — prototype not polluted
- Perlindungan semacam ini juga penting dalam pustaka dan framework.
Pertimbangan performa
Terkait dengan performa, pertimbangkan hal-hal berikut:.
- Hindari perubahan prototipe yang sering (
Object.setPrototypeOf) atau penambahan/penghapusan properti secara dinamis, karena dapat menghambat optimisasi mesin. - Saat membuat banyak objek kecil, optimasi menjadi lebih efektif jika Anda menggunakan objek dengan struktur yang seragam (set properti yang sama).
- Penyalinan mendalam membutuhkan biaya tinggi. Minimalkan penggunaannya atau pertimbangkan pembaruan berbasis selisih (diff).
Ringkasan
Object adalah inti dari JavaScript, menyediakan berbagai fitur seperti pembuatan objek, kontrol properti, pewarisan, penyalinan, dan pengelolaan mutabilitas. Penting untuk memahami API seperti Object.defineProperty, Object.assign, dan Object.freeze, serta merancang dengan hati-hati untuk menghindari bahaya seperti pencemaran prototipe dan penyalinan dangkal.
Anda dapat mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Silakan periksa juga saluran YouTube kami.