Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> JavaScript

วัตถุประสงค์ของ Self-Executing Function (IIFE) ใน JavaScript

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 แทนได้ในส่วนใหญ่