ES2015 dan yang lebih baru
Dalam ES2015, perusakan parameter dapat digunakan untuk mensimulasikan parameter bernama. Ini akan meminta penelepon untuk melewati objek, tetapi Anda dapat menghindari semua pemeriksaan di dalam fungsi jika Anda juga menggunakan parameter default:
myFunction({ param1 : 70, param2 : 175});
function myFunction({param1, param2}={}){
// ...function body...
}
// Or with defaults,
function myFunc({
name = 'Default user',
age = 'N/A'
}={}) {
// ...function body...
}
ES5
Ada cara untuk mendekati apa yang Anda inginkan, tetapi didasarkan pada output Function.prototype.toString
[ES5] , yang implementasinya tergantung pada tingkat tertentu, sehingga mungkin tidak kompatibel dengan browser.
Idenya adalah untuk mem-parsing nama parameter dari representasi string dari fungsi sehingga Anda dapat mengaitkan properti suatu objek dengan parameter yang sesuai.
Panggilan fungsi kemudian bisa terlihat seperti
func(a, b, {someArg: ..., someOtherArg: ...});
di mana a
dan b
adalah argumen posisi dan argumen terakhir adalah objek dengan argumen bernama.
Sebagai contoh:
var parameterfy = (function() {
var pattern = /function[^(]*\(([^)]*)\)/;
return function(func) {
// fails horribly for parameterless functions ;)
var args = func.toString().match(pattern)[1].split(/,\s*/);
return function() {
var named_params = arguments[arguments.length - 1];
if (typeof named_params === 'object') {
var params = [].slice.call(arguments, 0, -1);
if (params.length < args.length) {
for (var i = params.length, l = args.length; i < l; i++) {
params.push(named_params[args[i]]);
}
return func.apply(this, params);
}
}
return func.apply(null, arguments);
};
};
}());
Yang akan Anda gunakan sebagai:
var foo = parameterfy(function(a, b, c) {
console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);
});
foo(1, 2, 3); // a is 1 | b is 2 | c is 3
foo(1, {b:2, c:3}); // a is 1 | b is 2 | c is 3
foo(1, {c:3}); // a is 1 | b is undefined | c is 3
foo({a: 1, c:3}); // a is 1 | b is undefined | c is 3
DEMO
Ada beberapa kelemahan dari pendekatan ini (Anda telah diperingatkan!):
- Jika argumen terakhir adalah objek, itu diperlakukan sebagai "objek argumen bernama"
- Anda akan selalu mendapatkan argumen sebanyak yang Anda tetapkan dalam fungsi, tetapi beberapa dari mereka mungkin memiliki nilai
undefined
(yang berbeda dari tidak memiliki nilai sama sekali). Itu berarti Anda tidak dapat menggunakan arguments.length
untuk menguji berapa banyak argumen yang telah diajukan.
Alih-alih memiliki fungsi membuat wrapper, Anda juga bisa memiliki fungsi yang menerima fungsi dan berbagai nilai sebagai argumen, seperti
call(func, a, b, {posArg: ... });
atau bahkan meluas Function.prototype
sehingga Anda bisa melakukan:
foo.execute(a, b, {posArg: ...});