Ada beberapa aspek untuk argumen overloading di Javascript:
Argumen variabel - Anda dapat meneruskan set argumen yang berbeda (baik dalam tipe maupun kuantitas) dan fungsi akan berperilaku sesuai dengan argumen yang diteruskan padanya.
Argumen default - Anda dapat menentukan nilai default untuk argumen jika tidak dilewatkan.
Argumen bernama - Urutan argumen menjadi tidak relevan dan Anda cukup memberi nama argumen yang ingin Anda teruskan ke fungsi tersebut.
Di bawah ini adalah bagian tentang masing-masing kategori penanganan argumen ini.
Argumen Variabel
Karena javascript tidak memiliki jenis pemeriksaan pada argumen atau jumlah argumen yang diperlukan, Anda hanya dapat memiliki satu implementasi myFunc()yang dapat menyesuaikan dengan argumen apa yang diteruskan kepadanya dengan memeriksa jenis, keberadaan, atau jumlah argumen.
jQuery melakukan ini sepanjang waktu. Anda bisa membuat beberapa argumen opsional atau Anda bisa bercabang di fungsi Anda tergantung pada argumen apa yang diteruskan padanya.
Dalam mengimplementasikan jenis kelebihan beban ini, Anda memiliki beberapa teknik berbeda yang dapat Anda gunakan:
- Anda dapat memeriksa keberadaan argumen yang diberikan dengan memeriksa untuk melihat apakah nilai nama argumen yang dideklarasikan adalah
undefined.
- Anda dapat memeriksa jumlah total atau argumen dengan
arguments.length.
- Anda dapat memeriksa jenis argumen yang diberikan.
- Untuk jumlah variabel argumen, Anda dapat menggunakan
argumentspseudo-array untuk mengakses argumen yang diberikan dengan arguments[i].
Berikut beberapa contohnya:
Mari kita lihat obj.data()metode jQuery . Ini mendukung empat bentuk penggunaan yang berbeda:
obj.data("key");
obj.data("key", value);
obj.data();
obj.data(object);
Masing-masing memicu perilaku yang berbeda dan, tanpa menggunakan bentuk dinamis pemuatan berlebih ini, akan memerlukan empat fungsi terpisah.
Inilah cara seseorang dapat membedakan semua opsi ini dalam bahasa Inggris dan kemudian saya akan menggabungkan semuanya dalam kode:
// get the data element associated with a particular key value
obj.data("key");
Jika argumen pertama yang diteruskan ke .data()adalah string dan argumen kedua adalah undefined, maka pemanggil harus menggunakan formulir ini.
// set the value associated with a particular key
obj.data("key", value);
Jika argumen kedua tidak terdefinisi, maka setel nilai kunci tertentu.
// get all keys/values
obj.data();
Jika tidak ada argumen yang diberikan, kembalikan semua kunci / nilai dalam objek yang dikembalikan.
// set all keys/values from the passed in object
obj.data(object);
Jika tipe argumen pertama adalah objek biasa, maka setel semua kunci / nilai dari objek tersebut.
Inilah cara Anda dapat menggabungkan semua itu dalam satu set logika javascript:
// method declaration for .data()
data: function(key, value) {
if (arguments.length === 0) {
// .data()
// no args passed, return all keys/values in an object
} else if (typeof key === "string") {
// first arg is a string, look at type of second arg
if (typeof value !== "undefined") {
// .data("key", value)
// set the value for a particular key
} else {
// .data("key")
// retrieve a value for a key
}
} else if (typeof key === "object") {
// .data(object)
// set all key/value pairs from this object
} else {
// unsupported arguments passed
}
},
Kunci dari teknik ini adalah untuk memastikan bahwa semua bentuk argumen yang ingin Anda terima dapat diidentifikasi secara unik dan tidak pernah ada kebingungan tentang bentuk mana yang digunakan penelepon. Ini biasanya memerlukan pengurutan argumen dengan tepat dan memastikan bahwa ada cukup keunikan dalam jenis dan posisi argumen sehingga Anda selalu dapat membedakan bentuk mana yang digunakan.
Misalnya, jika Anda memiliki fungsi yang membutuhkan tiga argumen string:
obj.query("firstArg", "secondArg", "thirdArg");
Anda bisa dengan mudah membuat argumen ketiga opsional dan Anda bisa dengan mudah mendeteksi kondisi itu, tapi Anda tidak bisa membuat hanya argumen kedua opsional karena Anda tidak bisa membedakan yang mana yang dimaksudkan pemanggil untuk diteruskan karena tidak ada cara untuk mengidentifikasi jika yang kedua. argumen dimaksudkan sebagai argumen kedua atau argumen kedua dihilangkan jadi apa yang ada di tempat argumen kedua sebenarnya adalah argumen ketiga:
obj.query("firstArg", "secondArg");
obj.query("firstArg", "thirdArg");
Karena ketiga argumen memiliki tipe yang sama, Anda tidak dapat membedakan antara argumen yang berbeda sehingga Anda tidak tahu apa yang dimaksudkan oleh pemanggil. Dengan gaya pemanggilan ini, hanya argumen ketiga yang bisa menjadi opsional. Jika Anda ingin menghilangkan argumen kedua, argumen tersebut harus diteruskan sebagai null(atau beberapa nilai lain yang dapat dideteksi) dan kode Anda akan mendeteksi bahwa:
obj.query("firstArg", null, "thirdArg");
Berikut adalah contoh jQuery dari argumen opsional. kedua argumen bersifat opsional dan menggunakan nilai default jika tidak diteruskan:
clone: function( dataAndEvents, deepDataAndEvents ) {
dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
return this.map( function () {
return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
});
},
Berikut adalah contoh jQuery di mana argumennya bisa hilang atau salah satu dari tiga jenis berbeda yang memberi Anda empat kelebihan beban berbeda:
html: function( value ) {
if ( value === undefined ) {
return this[0] && this[0].nodeType === 1 ?
this[0].innerHTML.replace(rinlinejQuery, "") :
null;
// See if we can take a shortcut and just use innerHTML
} else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
value = value.replace(rxhtmlTag, "<$1></$2>");
try {
for ( var i = 0, l = this.length; i < l; i++ ) {
// Remove element nodes and prevent memory leaks
if ( this[i].nodeType === 1 ) {
jQuery.cleanData( this[i].getElementsByTagName("*") );
this[i].innerHTML = value;
}
}
// If using innerHTML throws an exception, use the fallback method
} catch(e) {
this.empty().append( value );
}
} else if ( jQuery.isFunction( value ) ) {
this.each(function(i){
var self = jQuery( this );
self.html( value.call(this, i, self.html()) );
});
} else {
this.empty().append( value );
}
return this;
},
Argumen Bernama
Bahasa lain (seperti Python) memungkinkan seseorang untuk melewatkan argumen bernama sebagai sarana untuk meneruskan hanya beberapa argumen dan membuat argumen tidak tergantung pada urutan mereka diteruskan. Javascript tidak secara langsung mendukung fitur argumen bernama. Pola desain yang biasa digunakan untuk menggantikannya adalah meneruskan peta properti / nilai. Ini bisa dilakukan dengan melewatkan objek dengan properti dan nilai atau di ES6 dan di atasnya, Anda sebenarnya bisa meneruskan objek Map itu sendiri.
Berikut contoh ES5 sederhana:
jQuery $.ajax()menerima bentuk penggunaan di mana Anda hanya meneruskannya satu parameter yang merupakan objek Javascript biasa dengan properti dan nilai. Properti mana yang Anda teruskan menentukan argumen / opsi mana yang diteruskan ke panggilan ajax. Beberapa mungkin diperlukan, banyak yang opsional. Karena mereka adalah properti pada suatu objek, tidak ada urutan tertentu. Faktanya, ada lebih dari 30 properti berbeda yang dapat diteruskan pada objek itu, hanya satu (url) yang diperlukan.
Berikut contohnya:
$.ajax({url: "http://www.example.com/somepath", data: myArgs, dataType: "json"}).then(function(result) {
// process result here
});
Di dalam $.ajax()implementasi, ia kemudian dapat menginterogasi properti mana yang diteruskan pada objek yang masuk dan menggunakannya sebagai argumen bernama. Ini bisa dilakukan dengan for (prop in obj)atau dengan memasukkan semua properti ke dalam larik dengan Object.keys(obj)dan kemudian mengiterasi larik itu.
Teknik ini sangat umum digunakan di Javascript ketika ada banyak argumen dan / atau banyak argumen bersifat opsional. Catatan: ini memberi tanggung jawab pada fungsi implementasi untuk memastikan bahwa ada sekumpulan argumen valid minimal dan untuk memberi pemanggil beberapa umpan balik debug apa yang hilang jika argumen yang diteruskan tidak mencukupi (mungkin dengan membuat pengecualian dengan pesan kesalahan yang membantu) .
Dalam lingkungan ES6, dimungkinkan untuk menggunakan destructuring untuk membuat properti / nilai default untuk objek yang diteruskan di atas. Ini dibahas lebih rinci dalam artikel referensi ini .
Inilah salah satu contoh dari artikel itu:
function selectEntries({ start=0, end=-1, step=1 } = {}) {
···
};
Ini membuat properti dan nilai default untuk start, enddan stepproperti pada objek yang diteruskan ke selectEntries()fungsi.
Nilai default untuk argumen fungsi
Di ES6, Javascript menambahkan dukungan bahasa bawaan untuk nilai default untuk argumen.
Sebagai contoh:
function multiply(a, b = 1) {
return a*b;
}
multiply(5); // 5
Penjelasan lebih lanjut tentang cara ini dapat digunakan di sini di MDN .