ใช้ arguments object (array-like) หรือ Rest Parameters (...args) (ES6) เพื่อรับจำนวน arguments ไม่จำกัด
ตัวอย่างจากบทความ (arguments object)
<html>
<body>
<script>
function functionArgument(val1, val2, val3) {
var res = "";
res += "Expected Arguments: " + functionArgument.length;
res += "<br />";
res += "Current Arguments : " + arguments.length;
res += "<br />";
res += "Each argument = ";
for (p = 0; p < arguments.length; p++) {
res += "<br />";
res += functionArgument.arguments[p]; // deprecated
res += " ";
}
document.write(res);
}
functionArgument(20, 50, 80, "Demo Text!", "Hello World", new Date());
</script>
</body>
</html>
⚠️ หมายเหตุ:functionArgument.argumentsเป็น deprecated ควรใช้argumentsโดยตรงใน scope ของฟังก์ชัน
Rest Parameters (...args) - ES6 (แนะนำ)
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
sum(); // 0
sum(1); // 1
sum(1, 2, 3); // 6
sum(1, 2, 3, 4, 5); // 15
// รวมกับพารามิเตอร์ปกติ
function greet(greeting, ...names) {
return names.map(name => `${greeting}, ${name}!`).join(' ');
}
greet('Hello', 'John', 'Jane', 'Bob');
// "Hello, John! Hello, Jane! Hello, Bob!"
arguments Object (Legacy)
function oldStyle() {
// arguments เป็น array-like (มี length, index แต่ไม่มี map, filter, etc.)
console.log(arguments.length);
console.log(arguments[0]);
// แปลงเป็น array จริง
const args = Array.from(arguments);
// หรือ (เก่า)
const args2 = Array.prototype.slice.call(arguments);
// หรือ ES6
const args3 = [...arguments];
return args.reduce((sum, n) => sum + n, 0);
}
ความแตกต่างสำคัญ
| คุณสมบัติ | arguments | Rest Parameters (...args) |
|---|---|---|
| ชนิดข้อมูล | Array-like object | Array จริง |
| Arrow Function | ไม่มี (ใช้ของ parent) | มีของตัวเอง |
| Named Parameters | รวมทั้งหมด | เฉพาะที่เหลือหลัง named params |
| Methods | ไม่มี map, filter, etc. | มีครบ (Array methods) |
| Strict Mode | ไม่สามารถเข้าถึงได้ในบางกรณี | ทำงานได้ปกติ |
ตัวอย่างการใช้งานจริง
1. Wrapper/Decorator Function
function logger(fn) {
return function(...args) {
console.log('Calling:', fn.name, args);
const result = fn.apply(this, args);
console.log('Result:', result);
return result;
};
}
const loggedAdd = logger((a, b) => a + b);
loggedAdd(1, 2); // Logs และคืน 3
2. Event Emitter Pattern
class EventEmitter {
constructor() {
this.events = {};
}
on(event, handler) {
(this.events[event] = this.events[event] || []).push(handler);
}
emit(event, ...args) {
(this.events[event] || []).forEach(handler => handler(...args));
}
}
const emitter = new EventEmitter();
emitter.on('data', (id, value, timestamp) => {
console.log(id, value, timestamp);
});
emitter.emit('data', 1, 'hello', Date.now());
3. Curry/Partial Application
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
}
return (...moreArgs) => curried.apply(this, [...args, ...moreArgs]);
};
}
const add = (a, b, c) => a + b + c;
const curriedAdd = curry(add);
curriedAdd(1)(2)(3); // 6
curriedAdd(1, 2)(3); // 6