Bahan, terjemahan yang kami terbitkan hari ini, dikhususkan untuk studi objek - salah satu esensi utama dari JavaScript. Ini dirancang terutama untuk pengembang pemula yang ingin merampingkan pengetahuan mereka tentang objek.

Objek dalam JavaScript adalah koleksi dinamis properti yang, di samping itu, berisi properti "tersembunyi" yang merupakan prototipe objek. Properti objek ditandai oleh kunci dan nilai. Mari kita mulai percakapan tentang objek JS dengan kunci.
Kunci properti objek
Kunci properti objek adalah string unik. Anda dapat menggunakan dua metode untuk mengakses properti: mengaksesnya melalui suatu periode dan menentukan kunci objek dalam tanda kurung. Saat mengakses properti melalui titik, kuncinya harus berupa pengidentifikasi JavaScript yang valid. Pertimbangkan sebuah contoh:
let obj = { message : "A message" } obj.message //"A message" obj["message"] //"A message"
Saat mencoba mengakses properti objek yang tidak ada, pesan kesalahan tidak akan muncul, tetapi nilai yang
undefined
akan dikembalikan:
obj.otherProperty
Saat menggunakan tanda kurung siku untuk mengakses properti, Anda dapat menggunakan kunci yang bukan pengidentifikasi JavaScript yang valid (misalnya, kunci tersebut dapat berupa string yang berisi spasi). Mereka dapat memiliki nilai apa pun yang dapat dilemparkan ke string:
let french = {}; french["merci beaucoup"] = "thank you very much"; french["merci beaucoup"];
Jika nilai-nilai non-string digunakan sebagai kunci, mereka secara otomatis dikonversi ke string (menggunakan, jika mungkin, metode
toString()
):
et obj = {}; //Number obj[1] = "Number 1"; obj[1] === obj["1"]; //true //Object let number1 = { toString : function() { return "1"; } } obj[number1] === obj["1"]; //true
Dalam contoh ini, objek
number1
digunakan sebagai kunci. Saat mencoba mengakses properti, properti itu dikonversi ke baris
1
, dan hasil konversi ini digunakan sebagai kunci.
Nilai Properti Obyek
Properti objek dapat berupa nilai, objek, atau fungsi primitif.
▍Object sebagai nilai properti objek
Objek dapat ditempatkan di objek lain. Pertimbangkan
sebuah contoh :
let book = { title : "The Good Parts", author : { firstName : "Douglas", lastName : "Crockford" } } book.author.firstName;
Pendekatan serupa dapat digunakan untuk membuat ruang nama:
let app = {}; app.authorService = { getAuthors : function() {} }; app.bookService = { getBooks : function() {} };
▍ Berfungsi sebagai nilai properti objek
Ketika fungsi digunakan sebagai nilai properti objek, biasanya menjadi metode objek. Di dalam metode, untuk mengakses objek saat ini, gunakan
this
.
Namun kata kunci ini, mungkin memiliki arti yang berbeda, tergantung pada bagaimana fungsinya dipanggil.
Di sini Anda dapat membaca tentang situasi di mana
this
kehilangan konteks.
Sifat dinamis dari objek
Objek dalam JavaScript, pada dasarnya, adalah entitas yang dinamis. Anda dapat menambahkan properti ke mereka kapan saja, hal yang sama berlaku untuk menghapus properti:
let obj = {}; obj.message = "This is a message"; // obj.otherMessage = "A new message"; // delete obj.otherMessage; //
Objek sebagai array asosiatif
Objek dapat dianggap sebagai array asosiatif. Kunci array asosiatif adalah nama properti objek. Untuk mengakses kunci, Anda tidak perlu melihat semua properti, yaitu operasi mengakses kunci array asosiatif berdasarkan objek dilakukan dalam O (1) waktu.
Prototipe objek
Objek memiliki tautan "tersembunyi",
__proto__
, menunjuk ke objek prototipe dari mana objek mewarisi properti.
Misalnya, objek yang dibuat menggunakan objek literal memiliki tautan ke
Object.prototype
:
var obj = {}; obj.__proto__ === Object.prototype;
▍ Objek kosong
Seperti yang baru saja kita lihat, objek "kosong",
{}
, sebenarnya tidak begitu kosong, karena berisi referensi ke
Object.prototype
. Untuk membuat objek yang benar-benar kosong, Anda perlu menggunakan konstruksi berikut:
Object.create(null)
Berkat ini, sebuah objek tanpa prototipe akan dibuat. Objek seperti itu biasanya digunakan untuk membuat array asosiatif.
▍ Rantai Prototipe
Objek prototipe dapat memiliki prototipe sendiri. Jika Anda mencoba mengakses properti dari objek yang tidak ada di dalamnya, JavaScript akan mencoba menemukan properti ini dalam prototipe objek ini, dan jika properti yang diinginkan tidak ada di sana, upaya akan dilakukan untuk menemukannya di prototipe prototipe. Ini akan berlanjut sampai properti yang diinginkan ditemukan, atau sampai akhir rantai prototipe tercapai.
Nilai Jenis Primitif dan Pembungkus Objek
JavaScript memungkinkan Anda untuk bekerja dengan nilai tipe primitif sebagai objek, dalam arti bahwa bahasa tersebut memungkinkan Anda untuk mengakses properti dan metode mereka.
(1.23).toFixed(1); //"1.2" "text".toUpperCase(); //"TEXT" true.toString(); //"true"
Apalagi, tentu saja, nilai tipe primitif bukanlah objek.
Untuk mengatur akses ke "properti" nilai-nilai tipe primitif, JavaScript, jika perlu, membuat objek wrapper, yang, setelah mereka menjadi tidak perlu, dihancurkan. Proses membuat dan menghancurkan objek pembungkus dioptimalkan oleh mesin JS.
Pembungkus objek memiliki nilai numerik, string, dan tipe logis. Objek dari tipe yang sesuai diwakili oleh fungsi konstruktor
Number
,
String
, dan
Boolean
.
Prototipe Tertanam
Objek Number mewarisi properti dan metode dari prototipe
Number.prototype
, yang merupakan turunan dari
Object.prototype
:
var no = 1; no.__proto__ === Number.prototype; //true no.__proto__.__proto__ === Object.prototype; //true
Prototipe objek string adalah
String.prototype
. Prototipe objek boolean adalah
Boolean.prototype
. Prototipe array (yang juga objek) adalah
Array.prototype
.
Fungsi dalam JavaScript juga objek yang memiliki prototipe
Function.prototype
. Fungsi memiliki metode seperti
bind()
,
apply()
dan
call()
.
Semua objek, fungsi, dan objek yang mewakili nilai tipe primitif (kecuali untuk nilai
null
dan
undefined
) mewarisi properti dan metode dari
Object.prototype
. Ini mengarah pada fakta bahwa, misalnya, mereka semua memiliki metode
toString()
.
Memperluas objek tertanam dengan polyfill
JavaScript memudahkan untuk memperluas objek yang disematkan dengan fitur baru menggunakan apa yang disebut polyfill. Polyfill adalah potongan kode yang mengimplementasikan fitur yang tidak didukung oleh browser apa pun.
▍Gunakan polyfill
Misalnya, ada
polyfill untuk metode
Object.assign()
. Ini memungkinkan Anda untuk menambahkan fungsi baru ke
Object
jika tidak tersedia di dalamnya.
Hal yang sama berlaku untuk
polyfill Array.from()
, yang, jika metode
from()
tidak ada di objek
Array
, lengkapi dengan metode ini.
▍ Polyfill dan prototipe
Dengan bantuan polyfill, metode baru dapat ditambahkan ke prototipe objek. Misalnya,
polyfill untuk
String.prototype.trim()
memungkinkan Anda untuk melengkapi semua objek string dengan metode
trim()
:
let text = " A text "; text.trim(); //"A text"
Array.prototype.find()
untuk
Array.prototype.find()
memungkinkan Anda untuk melengkapi semua array dengan metode
find()
.
Array.prototype.findIndex()
untuk
Array.prototype.findIndex()
bekerja dengan cara yang sama:
let arr = ["A", "B", "C", "D", "E"]; arr.indexOf("C");
Warisan tunggal
Perintah
Object.create()
memungkinkan Anda membuat objek baru dengan objek prototipe yang diberikan. Perintah ini digunakan dalam JavaScript untuk menerapkan mekanisme pewarisan tunggal. Pertimbangkan
sebuah contoh :
let bookPrototype = { getFullTitle : function(){ return this.title + " by " + this.author; } } let book = Object.create(bookPrototype); book.title = "JavaScript: The Good Parts"; book.author = "Douglas Crockford"; book.getFullTitle();
Warisan berganda
Perintah
Object.assign()
menyalin properti dari satu atau lebih objek ke objek target. Ini dapat digunakan untuk mengimplementasikan beberapa skema pewarisan. Berikut ini
sebuah contoh :
let authorDataService = { getAuthors : function() {} }; let bookDataService = { getBooks : function() {} }; let userDataService = { getUsers : function() {} }; let dataService = Object.assign({}, authorDataService, bookDataService, userDataService ); dataService.getAuthors(); dataService.getBooks(); dataService.getUsers();
Objek yang Tidak Berubah
Perintah
Object.freeze()
memungkinkan Anda untuk "membekukan" suatu objek. Anda tidak dapat menambahkan properti baru ke objek seperti itu. Properti tidak dapat dihapus, juga nilainya tidak dapat diubah. Dengan menggunakan perintah ini, suatu objek menjadi tidak berubah atau tidak berubah:
"use strict"; let book = Object.freeze({ title : "Functional-Light JavaScript", author : "Kyle Simpson" }); book.title = "Other title";//: Cannot assign to read only property 'title'
Perintah
Object.freeze()
melakukan apa yang disebut "pembekuan dangkal" objek. Ini berarti bahwa objek yang bersarang di objek "beku" dapat dimodifikasi. Untuk melakukan "pembekuan yang dalam" dari suatu objek, Anda perlu "membekukan" secara rekursif semua propertinya.
Objek Kloning
Untuk membuat klon (salinan) objek, Anda bisa menggunakan perintah
Object.assign()
:
let book = Object.freeze({ title : "JavaScript Allongé", author : "Reginald Braithwaite" }); let clone = Object.assign({}, book);
Perintah ini melakukan penyalinan objek yang dangkal, yaitu hanya menyalin properti tingkat atas. Objek bersarang ternyata umum untuk objek asli dan salinannya.
Objek literal
Literal objek memberi pengembang cara sederhana dan mudah untuk membuat objek:
let timer = { fn : null, start : function(callback) { this.fn = callback; }, stop : function() {}, }
Namun, metode membuat objek ini memiliki kelemahan. Secara khusus, dengan pendekatan ini, semua properti objek tersedia untuk umum, metode objek dapat didefinisikan ulang, mereka tidak dapat digunakan untuk membuat instance baru dari objek yang sama:
timer.fn;//null timer.start = function() { console.log("New implementation"); }
Metode Object.create ()
Dua masalah yang disebutkan di atas dapat diselesaikan melalui penggunaan bersama metode
Object.create()
dan
Object.freeze()
.
Kami menerapkan teknik ini pada contoh kami sebelumnya. Pertama, buat prototipe
timerPrototype
beku yang berisi semua metode yang dibutuhkan oleh berbagai instance objek. Setelah itu, buat objek yang merupakan penerus
timerPrototype
:
let timerPrototype = Object.freeze({ start : function() {}, stop : function() {} }); let timer = Object.create(timerPrototype); timer.__proto__ === timerPrototype; //true
Jika prototipe dilindungi dari perubahan, objek yang pewarisnya tidak akan dapat mengubah properti yang ditentukan dalam prototipe. Sekarang metode
start()
dan
stop()
tidak dapat diganti:
"use strict"; timer.start = function() { console.log("New implementation"); }
Object.create(timerPrototype)
dapat digunakan untuk membuat beberapa objek dengan prototipe yang sama.
Fungsi konstruktor
JavaScript memiliki apa yang disebut fungsi konstruktor, yang merupakan "gula sintaksis" untuk melakukan langkah-langkah di atas untuk membuat objek baru. Pertimbangkan
sebuah contoh :
function Timer(callback){ this.fn = callback; } Timer.prototype = { start : function() {}, stop : function() {} } function getTodos() {} let timer = new Timer(getTodos);
Anda dapat menggunakan fungsi apa pun sebagai konstruktor. Konstruktor disebut menggunakan kata kunci
new
. Objek yang dibuat menggunakan fungsi konstruktor bernama
FunctionConstructor
akan menerima prototipe
FunctionConstructor.prototype
:
let timer = new Timer(); timer.__proto__ === Timer.prototype;
Di sini, untuk mencegah perubahan prototipe, sekali lagi, Anda dapat membekukan prototipe:
Timer.prototype = Object.freeze({ start : function() {}, stop : function() {} });
▍ Kata kunci baru
Ketika perintah dari bentuk
new Timer()
dijalankan, tindakan yang sama dilakukan ketika fungsi
newTimer()
melakukan di bawah ini:
function newTimer(){ let newObj = Object.create(Timer.prototype); let returnObj = Timer.call(newObj, arguments); if(returnObj) return returnObj; return newObj; }
Objek baru dibuat di sini, prototipe di antaranya adalah
Timer.prototype
. Kemudian fungsi
Timer
disebut, mengatur bidang untuk objek baru.
Kata kunci kelas
ECMAScript 2015 memperkenalkan cara baru untuk melakukan tindakan di atas, yang merupakan kumpulan “gula sintaksis” lainnya. Kita berbicara tentang kata kunci
class
dan konstruksi terkait yang terkait dengannya. Pertimbangkan
sebuah contoh :
class Timer{ constructor(callback){ this.fn = callback; } start() {} stop() {} } Object.freeze(Timer.prototype);
Objek yang dibuat menggunakan kata kunci
class
berdasarkan kelas bernama
ClassName
akan memiliki prototipe
ClassName.prototype
. Saat membuat objek berdasarkan kelas, gunakan kata kunci
new
:
let timer= new Timer(); timer.__proto__ === Timer.prototype;
Menggunakan kelas tidak membuat prototipe tidak dapat diubah. Jika perlu, mereka harus "dibekukan" dengan cara yang sama seperti yang sudah kita lakukan:
Object.freeze(Timer.prototype);
Warisan Berbasis Prototipe
Dalam JavaScript, objek mewarisi properti dan metode dari objek lain. Fungsi dan kelas konstruktor adalah "gula sintaksis" untuk membuat objek prototipe yang berisi semua metode yang diperlukan. Menggunakannya, objek baru dibuat yang merupakan pewaris prototipe, sifat-sifatnya, khusus untuk contoh tertentu, diatur menggunakan fungsi konstruktor atau menggunakan mekanisme kelas.
Akan lebih baik jika fungsi dan kelas konstruktor secara otomatis dapat membuat prototipe tidak berubah.
Kekuatan warisan prototipe adalah penghematan memori. Faktanya adalah bahwa prototipe dibuat hanya sekali, setelah semua objek dibuat atas dasar menggunakannya.
▍ Masalah kurangnya mekanisme enkapsulasi bawaan
Templat pewarisan prototipe tidak menggunakan pemisahan sifat-sifat objek menjadi pribadi dan publik. Semua properti objek tersedia untuk umum.
Sebagai contoh, perintah
Object.keys()
mengembalikan array yang berisi semua kunci properti objek. Itu dapat digunakan untuk beralih pada semua properti dari suatu objek:
function logProperty(name){ console.log(name); // console.log(obj[name]); // } Object.keys(obj).forEach(logProperty);
Ada satu pola yang meniru properti pribadi, bergantung pada kenyataan bahwa pengembang tidak akan mengakses properti yang namanya dimulai dengan garis bawah (
_
):
class Timer{ constructor(callback){ this._fn = callback; this._timerId = 0; } }
Fitur Pabrik
Objek yang dienkapsulasi dalam JavaScript dapat dibuat menggunakan fungsi pabrik. Ini terlihat seperti ini:
function TodoStore(callback){ let fn = callback; function start() {}, function stop() {} return Object.freeze({ start, stop }); }
Di sini variabel
fn
bersifat pribadi. Hanya metode
start()
dan
stop()
yang tersedia untuk umum. Metode-metode ini tidak dapat dimodifikasi secara eksternal. Kata kunci ini tidak digunakan di sini, oleh karena itu, ketika menggunakan metode ini membuat objek, masalah kehilangan konteks ini tidak relevan.
Perintah
return
menggunakan objek literal yang hanya berisi fungsi. Selain itu, fungsi-fungsi ini dinyatakan tertutup, mereka berbagi keadaan umum. Untuk membekukan API publik dari suatu objek, perintah
Object.freeze()
sudah dikenal
Object.freeze()
.
Di sini, dalam contoh, kami menggunakan objek
Timer
. Dalam materi
ini Anda dapat menemukan implementasi penuhnya.
Ringkasan
Dalam JavaScript, nilai tipe primitif, objek biasa, dan fungsi diperlakukan sebagai objek. Objek memiliki sifat yang dinamis, mereka dapat digunakan sebagai array asosiatif. Objek adalah pewaris objek lain. Fungsi dan kelas konstruktor adalah "gula sintaksis", yang memungkinkan Anda membuat objek berdasarkan prototipe. Anda bisa menggunakan metode
Object.create()
untuk mengatur pewarisan tunggal, dan
Object.create()
untuk mengatur beberapa pewarisan. Anda dapat menggunakan fungsi pabrik untuk membuat objek yang dienkapsulasi.
Pembaca yang budiman! Jika Anda datang ke JavaScript dari bahasa lain, beri tahu kami apa yang Anda suka atau tidak suka tentang objek JS, dibandingkan dengan implementasi objek dalam bahasa yang sudah Anda ketahui.
