Self-Executing Function หรือ IIFE (Immediately Invoked Function Expression) คือฟังก์ชันที่ถูกสร้างและเรียกใช้ทันที วัตถุประสงค์หลักคือ สร้าง Scope แยก (Isolation) ป้องกันตัวแปรรั่วไหลสู่ Global Scope
ตัวอย่างจากบทความ
<html>
<body>
<script>
(function() {
var privateVar = "I'm private!";
console.log(privateVar); // เข้าถึงได้
})();
console.log(privateVar); // ReferenceError - เข้าถึงไม่ได้
</script>
</body>
</html>
ไวยากรณ์และการทำงาน
(function() {
// code
})();
// แยกส่วน:
// 1. function() { ... } → Function Expression
// 2. ( ... ) → Grouping Operator (ทำให้เป็น Expression)
// 3. () → เรียกใช้ทันที (Invocation)
รูปแบบต่างๆ ของ IIFE
// Standard (แนะนำ)
(function() { })();
// Leading operators (สั้นกว่า 1 byte)
!function() { }();
+function() { }();
-function() { }();
~function() { }();
void function() { }();
// Arrow function IIFE (ES6)
(() => { })();
// Async IIFE (ES2017)
(async () => {
const data = await fetchData();
console.log(data);
})();
ประโยชน์หลัก
1. Variable Isolation (ไม่มลพิษ Global Scope)
// ไม่ใช้ IIFE - global pollution
var config = { apiUrl: '/api' };
var utils = { formatDate: () => {} };
// ใช้ IIFE - encapsulated
const MyModule = (function() {
var config = { apiUrl: '/api' };
function formatDate() { ... }
return {
getConfig: () => config,
formatDate
};
})();
2. Module Pattern (Revealing Module)
const Counter = (function() {
let count = 0; // Private
function increment() {
count++;
return count;
}
function decrement() {
count--;
return count;
}
function getCount() {
return count;
}
// Public API
return {
increment,
decrement,
getCount
};
})();
Counter.increment(); // 1
Counter.increment(); // 2
Counter.getCount(); // 2
// count ไม่เข้าถึงได้จากนอก
3. Avoid Closure Issues ใน Loop (var)
// ปัญหา: var ใน loop
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // พิมพ์ 3, 3, 3
}
// แก้ด้วย IIFE (เก่า)
for (var i = 0; i < 3; i++) {
(function(i) {
setTimeout(() => console.log(i), 100);
})(i); // พิมพ์ 0, 1, 2
}
// แก้ด้วย let (ES6 - แนะนำ)
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 0, 1, 2
}
4. One-time Initialization
const appConfig = (function() {
const env = process.env.NODE_ENV || 'development';
const apiUrl = env === 'production'
? 'https://api.prod.com'
: 'https://localhost:3000';
return { env, apiUrl };
})();
Modern Alternative: ES Modules
// utils.js (Module scope อัตโนมัติ)
export const PI = 3.14159;
export function circleArea(r) { return PI * r * r; }
// main.js
import { PI, circleArea } from './utils.js';
- ES Modules มี Module Scope อัตโนมัติ (ไม่ต้อง IIFE)
- Static analysis, Tree shaking, Better tooling
- ใช้ใน Production แล้ว (with bundler หรือ native ES modules)
สรุป
IIFE = ฟังก์ชันรันทันที สร้าง Private Scope
ใช้สำหรับ: Encapsulation, Module Pattern, Loop Closure Fix, Init Code
Modern: ใช้ ES Modules แทนได้ในส่วนใหญ่