본문으로 건너뛰기

เนื้อหาภาษาไทย / 태국어 콘텐츠

시스템 가이드 검수 완료된 콘텐츠

Decorators

บทความนี้แนะนำ Decorators ใน JavaScript ซึ่งเป็นคุณสมบัติที่ช่วยเพิ่ม meta programming ให้กับคลาสและ methods โดยใช้ syntax `@decoratorName` เพื่อปรับเปลี่ยนหรือ...

Decorators: เพิ่ม Meta Programming ใน JavaScript

ในบทก่อนหน้านี้ เราได้เรียนรู้เกี่ยวกับ getter และ setter methods ซึ่งเป็นเครื่องมือที่มีประโยชน์ในการควบคุมการเข้าถึงและแก้ไข properties ของ object ในบทนี้ เราจะก้าวไปอีกขั้นด้วยการเรียนรู้เกี่ยวกับ Decorators ซึ่งเป็นคุณสมบัติที่ช่วยให้เราสามารถเพิ่ม meta programming ให้กับคลาสและ methods ของเราได้

Decorators เป็นคุณสมบัติที่ยังอยู่ในช่วง Proposal (Stage 3) ใน ECMAScript แต่ได้รับการสนับสนุนอย่างกว้างขวางจากเครื่องมือต่างๆ เช่น TypeScript และ Babel (พร้อม plugin ที่เหมาะสม) Decorators ช่วยให้เราสามารถปรับเปลี่ยนหรือเพิ่มความสามารถให้กับคลาส, methods, properties, หรือ parameters ได้โดยไม่ต้องแก้ไขโค้ดเดิมโดยตรง ทำให้โค้ดของเรามีความ modular และบำรุงรักษาง่ายขึ้น

Decorator Syntax

Decorator syntax ใน JavaScript ใช้เครื่องหมาย @ ตามด้วยชื่อของ decorator ที่ต้องการนำไปใช้ Decorator จะถูกวางไว้เหนือส่วนของโค้ดที่ต้องการตกแต่ง (decorate) เช่น คลาส, method, หรือ property

@decoratorName
class MyClass {
  @decoratorName
  myMethod() {
    // ...
  }
}

Class Decorators

Class decorators เป็น decorators ที่ใช้กับคลาส มีหน้าที่ในการปรับเปลี่ยนหรือเพิ่มความสามารถให้กับคลาสนั้นๆ Class decorator จะรับ constructor function ของคลาสเป็น argument และสามารถ return constructor function ใหม่เพื่อแทนที่ constructor function เดิมได้

เหตุผลเชิงออกแบบ: Class decorators ช่วยให้เราสามารถเพิ่ม functionality ข้ามคลาสต่างๆ ได้อย่างง่ายดาย เช่น การ logging, การ authorization, หรือการ dependency injection โดยไม่ต้องแก้ไขโค้ดของแต่ละคลาสโดยตรง

ตัวอย่าง:

function logClass(constructor) {
  return class extends constructor {
    constructor(...args) {
      super(...args);
      console.log(`Creating a new instance of ${constructor.name}`);
    }
  };
}

@logClass
class User {
  constructor(name) {
    this.name = name;
  }
}

const user = new User("John"); // Output: Creating a new instance of User

ในตัวอย่างนี้ logClass เป็น class decorator ที่รับ constructor ของคลาส User เป็น argument จากนั้น return คลาสใหม่ที่ extends จาก constructor เดิม และเพิ่ม logging message ใน constructor ของคลาสใหม่ เมื่อเราสร้าง instance ของ User จะมี logging message ปรากฏใน console

Trade-offs: การใช้ class decorators อาจทำให้โค้ดซับซ้อนขึ้นเล็กน้อย โดยเฉพาะอย่างยิ่งเมื่อมี decorators หลายตัวซ้อนกัน อย่างไรก็ตาม ข้อดีของการ modularity และการ reuseability มักจะคุ้มค่ากว่าข้อเสีย

Method Decorators

Method decorators เป็น decorators ที่ใช้กับ methods มีหน้าที่ในการปรับเปลี่ยนหรือเพิ่มความสามารถให้กับ method นั้นๆ Method decorator จะรับ arguments 3 ตัว:

  • target: Prototype ของคลาส
  • propertyKey: ชื่อของ method
  • descriptor: Property descriptor ของ method

Property descriptor เป็น object ที่มี properties เช่น value (function ของ method), writable (boolean ว่า method สามารถเขียนทับได้หรือไม่), enumerable (boolean ว่า method จะถูกแสดงใน loop หรือไม่), และ configurable (boolean ว่า descriptor สามารถแก้ไขได้หรือไม่)

เหตุผลเชิงออกแบบ: Method decorators ช่วยให้เราสามารถเพิ่ม functionality เฉพาะเจาะจงให้กับแต่ละ method ได้ เช่น การ caching, การ profiling, หรือการ authorization

ตัวอย่าง:

function logMethod(target, propertyKey, descriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function (...args) {
    console.log(`Calling method ${propertyKey} with arguments: ${args}`);
    const result = originalMethod.apply(this, args);
    console.log(`Method ${propertyKey} returned: ${result}`);
    return result;
  };

  return descriptor;
}

class Calculator {
  @logMethod
  add(a, b) {
    return a + b;
  }
}

const calculator = new Calculator();
calculator.add(2, 3);
// Output:
// Calling method add with arguments: 2,3
// Method add returned: 5

ในตัวอย่างนี้ logMethod เป็น method decorator ที่รับ target, propertyKey, และ descriptor เป็น arguments จากนั้นแก้ไข descriptor.value ให้เป็น function ใหม่ที่ logging การเรียกใช้ method และผลลัพธ์ของ method เดิม เมื่อเราเรียกใช้ calculator.add(2, 3) จะมี logging messages ปรากฏใน console

Trade-offs: การใช้ method decorators อาจทำให้ debugging ยากขึ้นเล็กน้อย เนื่องจากโค้ดที่ถูก execute จริงๆ อาจไม่ตรงกับโค้ดที่เราเขียนโดยตรง อย่างไรก็ตาม เครื่องมือ debugging ที่ดีมักจะสามารถ handle decorators ได้อย่างเหมาะสม

แนวปฏิบัติที่ดีในการใช้ Decorators

  • ใช้ decorators อย่างมีสติ: Decorators เป็นเครื่องมือที่มีประสิทธิภาพ แต่ควรใช้เฉพาะเมื่อจำเป็นจริงๆ เท่านั้น การใช้ decorators มากเกินไปอาจทำให้โค้ดซับซ้อนและอ่านยาก
  • เขียน decorators ที่ reuseable: พยายามเขียน decorators ที่สามารถนำไปใช้กับคลาสและ methods ต่างๆ ได้อย่างหลากหลาย
  • Document decorators อย่างชัดเจน: อธิบายว่า decorator ทำอะไร และมีผลกระทบอย่างไรต่อโค้ดที่ถูก decorate
  • ทดสอบ decorators อย่างละเอียด: ตรวจสอบให้แน่ใจว่า decorators ทำงานได้อย่างถูกต้อง และไม่ทำให้เกิด side effects ที่ไม่คาดฝัน

ข้อควรระวัง: เนื่องจาก Decorators ยังเป็นคุณสมบัติที่อยู่ในช่วง proposal การใช้งานจริงอาจแตกต่างกันไปขึ้นอยู่กับเครื่องมือและ environment ที่ใช้ ควรตรวจสอบ documentation ของ TypeScript หรือ Babel อย่างละเอียดก่อนใช้งาน

ในบทนี้ เราได้เรียนรู้เกี่ยวกับ Decorators ซึ่งเป็นคุณสมบัติที่ช่วยให้เราสามารถเพิ่ม meta programming ให้กับคลาสและ methods ของเราได้ Decorators ช่วยให้โค้ดของเรามีความ modular และบำรุงรักษาง่ายขึ้น ในบทถัดไป เราจะมาเรียนรู้เกี่ยวกับ WeakMap และ WeakSet ซึ่งเป็น data structures ที่มีประโยชน์ในการจัดการ memory ใน JavaScript

Office.in.th Custom Service

이 구조를 바탕으로 시스템을 개발하거나 맞춤 변경하고 싶으신가요?

Office.in.th는 엔터프라이즈 웹 애플리케이션, API 연동, 공공/민간 업무 관리 시스템을 설계·개발하며 장기 지원을 제공합니다.

소프트웨어 개발 서비스 보기