ES2015 trở lên
Trong ES2015, phá hủy tham số có thể được sử dụng để mô phỏng các tham số được đặt tên. Nó sẽ yêu cầu người gọi vượt qua một đối tượng, nhưng bạn có thể tránh tất cả các kiểm tra bên trong hàm nếu bạn cũng sử dụng các tham số mặc định:
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
Có một cách để đến gần với những gì bạn muốn, nhưng nó dựa trên đầu ra của Function.prototype.toString
[ES5] , đó là việc triển khai phụ thuộc ở một mức độ nào đó, vì vậy nó có thể không tương thích với nhiều trình duyệt.
Ý tưởng là phân tích các tên tham số từ biểu diễn chuỗi của hàm để bạn có thể liên kết các thuộc tính của một đối tượng với tham số tương ứng.
Một cuộc gọi chức năng sau đó có thể trông giống như
func(a, b, {someArg: ..., someOtherArg: ...});
trong đó a
và b
là các đối số vị trí và đối số cuối cùng là một đối tượng với các đối số được đặt tên.
Ví dụ:
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);
};
};
}());
Mà bạn sẽ sử dụng như:
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
BẢN GIỚI THIỆU
Có một số nhược điểm đối với phương pháp này (bạn đã được cảnh báo!):
- Nếu đối số cuối cùng là một đối tượng, nó được coi là "đối tượng đối số được đặt tên"
- Bạn sẽ luôn nhận được nhiều đối số như bạn đã xác định trong hàm, nhưng một số trong số chúng có thể có giá trị
undefined
(khác với không có giá trị nào cả). Điều đó có nghĩa là bạn không thể sử dụng arguments.length
để kiểm tra có bao nhiêu đối số đã được thông qua.
Thay vì có một hàm tạo trình bao bọc, bạn cũng có thể có một hàm chấp nhận một hàm và các giá trị khác nhau làm đối số, chẳng hạn như
call(func, a, b, {posArg: ... });
hoặc thậm chí mở rộng Function.prototype
để bạn có thể làm:
foo.execute(a, b, {posArg: ...});