DEV Community

Cover image for Proxy Pattern trong Javascript
Dinh Vo
Dinh Vo

Posted on

Proxy Pattern trong Javascript

Với một Proxy object, chúng ta có quyền kiểm soát các tương tác với một object nhất định, ví dụ: getting một value hoặc setting một value.

Hãy tạo một object person, đại diện là John Doe.

const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};
Enter fullscreen mode Exit fullscreen mode

Thay vì tương tác trực tiếp với object này, tôi muốn tương tác với một proxy object. Trong javascript, tôi có thể tạo một proxy bằng cách sử dụng từ khóa new Proxy

const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {});
Enter fullscreen mode Exit fullscreen mode

Argument thứ 2 của proxy là một object đại diện được gọi là handler. Trong handler object, tôi có thể xác định các hành vi cụ thể dựa trên loại tương tác. Mặc dù có nhiều methods mà tôi có thể thêm vào Proxy handler, 2 method phổ biến nhất là getset:

  • get: được gọi khi cố gắng access một property
  • set được gọi khi muốn modify một property Quy trình sẽ xảy ra như xau: Image description Thay vì tương tác trực tiếp với object person, tôi sẽ tương tác với personProxy. Hãy thêm các handlers vào proxyHandler. Khi muốn modify một property, do đó gọi method set trên proxy, tôi muốn proxy in value cũ và value mới, sau đó thực hiện ghi đè value của property. Khi cố gắng access một property, hãy gọi method get trên Proxy, tôi muốn proxy ghi lại một contains chứa key và value của property.
const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    console.log(`The value of ${prop} is ${obj[prop]}`);
  },
  set: (obj, prop, value) => {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    obj[prop] = value;
  }
});
Enter fullscreen mode Exit fullscreen mode

Tuyệt hãy xem đoạn code dưới dây, điều gì sẽ xảy ra?

const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    console.log(`The value of ${prop} is ${obj[prop]}`);
  },
  set: (obj, prop, value) => {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    obj[prop] = value;
    return true;
  }
});

personProxy.name; //The value of name is John Doe 
personProxy.age = 43; //Changed age from 42 to 43 
Enter fullscreen mode Exit fullscreen mode

Khi access name, proxy trả về một câu: The value of name is John Doe
khi modify age, proxy in Changed age from 42 to 43

Ngoài ra có thể bắt các validation của method proxy

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    if (!obj[prop]) {
      console.log(
        `Hmm.. this property doesn't seem to exist on the target object`
      );
    } else {
      console.log(`The value of ${prop} is ${obj[prop]}`);
    }
  },
  set: (obj, prop, value) => {
    if (prop === "age" && typeof value !== "number") {
      console.log(`Sorry, you can only pass numeric values for age.`);
    } else if (prop === "name" && value.length < 2) {
      console.log(`You need to provide a valid name.`);
    } else {
      console.log(`Changed ${prop} from ${obj[prop]} to ${value}.`);
      obj[prop] = value;
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

Hãy xem đoạn code dưới dây, điều gì sẽ xảy ra?

const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    if (!obj[prop]) {
      console.log(`Hmm.. this property doesn't seem to exist`);
    } else {
      console.log(`The value of ${prop} is ${obj[prop]}`);
    }
  },
  set: (obj, prop, value) => {
    if (prop === "age" && typeof value !== "number") {
      console.log(`Sorry, you can only pass numeric values for age.`);
    } else if (prop === "name" && value.length < 2) {
      console.log(`You need to provide a valid name.`);
    } else {
      console.log(`Changed ${prop} from ${obj[prop]} to ${value}.`);
      obj[prop] = value;
    }
    return true;
  }
});

personProxy.nonExistentProperty; //Hmm.. this property doesn't seem to exist
personProxy.age = "44"; //Sorry, you can only pass numeric values for age. 
personProxy.name = ""; //You need to provide a valid name. 
Enter fullscreen mode Exit fullscreen mode

Proxy made sure tôi không sủa đổi object person với các value không hợp lệ, điều này giúp tôi giữ cho dữ liệu của tôi tinh khiết(data pure)
Reflect
Js cung cấp một object gọi là Reflect, giúp tôi thao tác với đối tượng đích dễ dàng hơn khi làm việc với proxy.
Trước đây, tôi muốn modify và acces property trên một object bên trong proxy thông qua get, set bằng ky hiệu {}. Thay vào đó, tôi có thể sử dụng Reflect. Methods trên Reflect có cùng tên với các methods trên object đang xử lý.
Thay vì access property thông qua obj[prop], tôi có thể access hoặc modify property thông qua Reflect.get()Reflect.set(). Các methods nhận các arguments dưới dạng methods trên handle obejct.

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    console.log(`The value of ${prop} is ${Reflect.get(obj, prop)}`);
  },
  set: (obj, prop, value) => {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    Reflect.set(obj, prop, value);
  }
});
Enter fullscreen mode Exit fullscreen mode

Hãy xem đoạn code dưới dây:

const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    console.log(`The value of ${prop} is ${Reflect.get(obj, prop)}`);
  },
  set: (obj, prop, value) => {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    return Reflect.set(obj, prop, value);
  }
});

personProxy.name; //The value of name is John Doe 
personProxy.age = 43; //The value of name is John Doe 
personProxy.name = "Jane Doe"; //The value of name is John Doe 
Enter fullscreen mode Exit fullscreen mode

Proxy là một cách hiệu quả để control các behavior của một object. Một proxy có thể có nhiều use-cases: nó giúp validation, formatting, notifications, hoặc debugging.
Việc lạm dụng proxy hoặc thực hiện các thao tác nặng trên mỗi handler method có thể ảnh hưởng đến performance của app. Tốt nhất cũng không nên sử dụng proxy cho các đoạn code quan trọng về hiệu suất.

Top comments (0)