Apakah ada cara untuk mengizinkan vars "tidak terbatas" untuk suatu fungsi dalam JavaScript?
Contoh:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
Apakah ada cara untuk mengizinkan vars "tidak terbatas" untuk suatu fungsi dalam JavaScript?
Contoh:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
Jawaban:
Tentu, cukup gunakan arguments
objeknya.
function foo() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
arguments
adalah objek khusus "Array-like", yang berarti memiliki panjang, tetapi tidak ada fungsi array lainnya. Lihat developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… untuk informasi lebih lanjut, dan jawaban ini: stackoverflow.com/a/13145228/1766230
length
properti. Ini termasuk arguments
objek. Mengetahui hal ini, dan bahwa metode concat
mengembalikan salinan dari 'array yang' itu disebut, kita dapat dengan mudah mengkonversi arguments
objek untuk array nyata seperti ini: var args = [].concat.call(arguments)
. Beberapa orang lebih suka menggunakan Array.prototype.concat.call
, tetapi saya suka []
, mereka pendek dan manis!
[...arguments].join()
Di (sebagian besar) browser terbaru, Anda dapat menerima jumlah variabel argumen dengan sintaks ini:
function my_log(...args) {
// args is an Array
console.log(args);
// You can pass this array as parameters to another function
console.log(...args);
}
Ini sebuah contoh kecil:
function foo(x, ...args) {
console.log(x, args, ...args, arguments);
}
foo('a', 'b', 'c', z='d')
=>
a
Array(3) [ "b", "c", "d" ]
b c d
Arguments
0: "a"
1: "b"
2: "c"
3: "d"
length: 4
Dokumentasi dan lebih banyak contoh di sini: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters
Pilihan lain adalah meneruskan argumen Anda dalam objek konteks.
function load(context)
{
// do whatever with context.name, context.address, etc
}
dan gunakan seperti ini
load({name:'Ken',address:'secret',unused:true})
Ini memiliki keuntungan bahwa Anda dapat menambahkan argumen bernama sebanyak yang Anda inginkan, dan fungsinya dapat menggunakannya (atau tidak) sesuai keinginan.
context
argumen dengan kode dan menyebarkannya sebelum digunakan.
Saya setuju dengan jawaban Ken sebagai yang paling dinamis dan saya ingin melangkah lebih jauh. Jika fungsi yang Anda panggil beberapa kali dengan argumen yang berbeda - Saya menggunakan desain Ken tetapi kemudian menambahkan nilai default:
function load(context) {
var defaults = {
parameter1: defaultValue1,
parameter2: defaultValue2,
...
};
var context = extend(defaults, context);
// do stuff
}
Dengan cara ini, jika Anda memiliki banyak parameter tetapi tidak perlu mengaturnya dengan setiap panggilan ke fungsi, Anda cukup menentukan non-default. Untuk metode perluasan, Anda dapat menggunakan metode perluasan jQuery ( $.extend()
), membuat sendiri atau menggunakan yang berikut:
function extend() {
for (var i = 1; i < arguments.length; i++)
for (var key in arguments[i])
if (arguments[i].hasOwnProperty(key))
arguments[0][key] = arguments[i][key];
return arguments[0];
}
Ini akan menggabungkan objek konteks dengan default dan mengisi nilai yang tidak terdefinisi dalam objek Anda dengan default.
_.defaults()
Metode Underscore adalah alternatif yang sangat bagus untuk menggabungkan argumen yang ditentukan dan default.
Lebih baik menggunakan sintaks parameter istirahat seperti yang ditunjukkan Ramast.
function (a, b, ...args) {}
Saya hanya ingin menambahkan beberapa properti bagus dari ... argumen args
- Ini adalah array, dan bukan objek seperti argumen. Ini memungkinkan Anda untuk menerapkan fungsi seperti peta atau mengurutkan secara langsung.
- Itu tidak termasuk semua parameter tetapi hanya satu yang diteruskan dari itu. Misalnya fungsi (a, b, ... args) dalam hal ini args berisi argumen 3 ke arguments.length
Seperti yang sudah disebutkan, Anda dapat menggunakan arguments
objek untuk mengambil sejumlah variabel parameter fungsi.
Jika Anda ingin memanggil fungsi lain dengan argumen yang sama, gunakan apply
. Anda bahkan dapat menambah atau menghapus argumen dengan mengonversikannya arguments
ke array. Misalnya, fungsi ini menyisipkan beberapa teks sebelum masuk ke konsol:
log() {
let args = Array.prototype.slice.call(arguments);
args = ['MyObjectName', this.id_].concat(args);
console.log.apply(console, args);
}
Meskipun saya umumnya setuju bahwa pendekatan argumen yang disebutkan berguna dan fleksibel (kecuali jika Anda peduli tentang urutannya, dalam hal mana argumen paling mudah), saya memang khawatir tentang biaya pendekatan mbeasley (menggunakan default dan extends). Ini adalah jumlah biaya ekstrem yang harus diambil untuk menarik nilai default. Pertama, default didefinisikan di dalam fungsi, sehingga dihuni kembali pada setiap panggilan. Kedua, Anda dapat dengan mudah membaca nilai yang disebutkan dan mengatur default pada saat yang sama menggunakan ||. Tidak perlu lagi membuat dan menggabungkan objek baru untuk mendapatkan informasi ini.
function load(context) {
var parameter1 = context.parameter1 || defaultValue1,
parameter2 = context.parameter2 || defaultValue2;
// do stuff
}
Ini kira-kira jumlah kode yang sama (mungkin sedikit lebih), tetapi harus menjadi sebagian kecil dari biaya runtime.
(parameter1=context.parameter1)===undefined && (parameter1=defaultValue1)
atau untuk volume kode yang lebih sedikit, fungsi pembantu kecil seperti: function def(providedValue, default) {return providedValue !== undefined ? providedValue : defaultValue;} var parameter1 = def(context.parameter1, defaultValue1)
memberikan pola alternatif. Namun, maksud saya masih berdiri: membuat objek tambahan untuk setiap pemanggilan fungsi dan menjalankan loop mahal untuk menetapkan beberapa nilai default adalah jumlah overhead gila.
Sementara @roufamatic memang menunjukkan penggunaan kata kunci argumen dan @Ken menunjukkan contoh objek yang bagus untuk digunakan, saya merasa tidak benar-benar membahas apa yang terjadi dalam hal ini dan dapat membingungkan pembaca di masa depan atau menanamkan praktik buruk karena tidak secara eksplisit menyatakan fungsi. / Metode dimaksudkan untuk mengambil jumlah variabel argumen / parameter.
function varyArg () {
return arguments[0] + arguments[1];
}
Ketika pengembang lain melihat melalui kode Anda, sangat mudah untuk menganggap fungsi ini tidak mengambil parameter. Apalagi jika pengembang itu tidak mengetahui argumen kata kunci . Karena itu, ide yang baik untuk mengikuti pedoman gaya dan konsisten. Saya akan menggunakan Google untuk semua contoh.
Mari kita secara eksplisit menyatakan fungsi yang sama memiliki parameter variabel:
function varyArg (var_args) {
return arguments[0] + arguments[1];
}
Mungkin ada saat-saat ketika suatu objek dibutuhkan karena merupakan satu-satunya metode praktik terbaik dari peta data. Array asosiatif disukai dan tidak dianjurkan.
SIDENOTE: Kata kunci argumen sebenarnya mengembalikan kembali suatu objek menggunakan angka sebagai kunci. Warisan prototypal juga merupakan objek keluarga. Lihat akhir jawaban untuk penggunaan array yang tepat di JS
Dalam hal ini kita dapat secara eksplisit menyatakan ini juga. Catatan: konvensi penamaan ini tidak disediakan oleh Google tetapi merupakan contoh deklarasi eksplisit dari jenis param. Ini penting jika Anda ingin membuat pola pengetikan yang lebih ketat dalam kode Anda.
function varyArg (args_obj) {
return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});
Ini tergantung pada kebutuhan fungsi dan program Anda. Jika misalnya Anda hanya ingin mengembalikan basis nilai pada proses berulang di semua argumen yang disahkan maka pasti tetap dengan kata kunci argumen . Jika Anda membutuhkan definisi untuk argumen dan pemetaan data Anda maka metode objek adalah cara yang harus dilakukan. Mari kita lihat dua contoh dan kemudian kita selesai!
function sumOfAll (var_args) {
return arguments.reduce(function(a, b) {
return a + b;
}, 0);
}
sumOfAll(1,2,3); // returns 6
function myObjArgs(args_obj) {
// MAKE SURE ARGUMENT IS AN OBJECT OR ELSE RETURN
if (typeof args_obj !== "object") {
return "Arguments passed must be in object form!";
}
return "Hello "+args_obj.name+" I see you're "+args_obj.age+" years old.";
}
myObjArgs({name: "Brian", age: 31}); // returns 'Hello Brian I see you're 31 years old
Seperti disebutkan di bagian atas jawaban, kata kunci argumen sebenarnya mengembalikan sebuah objek. Karena ini, metode apa pun yang ingin Anda gunakan untuk sebuah array harus dipanggil. Contoh dari ini:
Array.prototype.map.call(arguments, function (val, idx, arr) {});
Untuk menghindari hal ini, gunakan parameter lainnya:
function varyArgArr (...var_args) {
return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5
Gunakan arguments
objek ketika di dalam fungsi untuk memiliki akses ke semua argumen yang dilewatkan.
Ketahuilah bahwa melewatkan Objek dengan properti yang dinamai Ken menyarankan menambah biaya pengalokasian dan melepaskan objek sementara untuk setiap panggilan. Melewati argumen normal dengan nilai atau referensi umumnya akan menjadi yang paling efisien. Untuk banyak aplikasi meskipun kinerjanya tidak kritis tetapi untuk beberapa hal itu bisa saja.