发布于 2026-01-05 3 阅读
0

对象代理的实际应用案例

对象代理的实际应用案例

标准定义

Proxy 对象允许您为另一个对象创建代理,该代理可以拦截和重新定义该对象的基本操作。

思维

我们来简化一下。

“使用处理程序自定义对象的行为”——广义上讲。

目标和处理程序

目标是代理所关注的对象。

处理程序或陷阱是作为第二个参数传递的函数,Proxy负责处理目标对象上的操作(例如get,等等)。set

new Proxy(target, handler);
Enter fullscreen mode Exit fullscreen mode

让我们来看一些例子,这些例子将进一步佐证该声明想要表达的意思。

处理默认值

设想一个脚本,用于将获奖者与他们赢得的奖品进行匹配,并且所有参与者都将获得安慰奖。

与使用冗长的语句或 switch 语句相比,更简洁的编码方法if-else是使用Proxy

const prizeRegistry = {
  karen: "First Prize - BMW X5",
  mark: "Second Prize - Scooty",
  athira: "Third Prize - Bicycle"
};

const prizeHandler = {
  get(obj, prop) {
    return prop in obj ?
      obj[prop] :
      "Consolation prize - Chocolate Bar";
  }
};

const prizeList = new Proxy(prizeRegistry, prizeHandler);

console.log(prizeList.karen);
// expected output: "First Prize - BMW X5"

console.log(prizeList.reena);
// expected output: "Consolation prize - Chocolate Bar"
Enter fullscreen mode Exit fullscreen mode

输入验证

如今,用户输入已成为大多数应用程序运行过程中不可或缺的一部分。验证机制旨在确保数据的准确性,但讽刺的是,随着时间的推移,负责验证的代码往往会因此而变得混乱不堪。

const validator = {
  set(obj, prop, value) {
    if (prop === 'weight') {
      if (!Number.isInteger(value)) {
        throw new TypeError('The weight is not an integer');
      }
      if (value > 200) {
        throw new RangeError('The weight seems invalid');
      }
    }

    // The default behavior to store the value
    obj[prop] = value;

    // Indicate success
    return true;
  }
};

const fish = new Proxy({}, validator);

fish.weight = 100;
console.log(fish.weight); 
// expected output: 100
fish.weight = 'small';    // Throws an exception
fish.weight = 300;        // Throws an exception
Enter fullscreen mode Exit fullscreen mode

通过属性查找数组项对象

const products = new Proxy([
  { name: 'Firefox', type: 'browser' },
  { name: 'SeaMonkey', type: 'browser' },
  { name: 'Thunderbird', type: 'mailer' }
],
{
  get(obj, prop) {
    // The default behavior to return the value; prop is usually an integer
    if (prop in obj) {
      return obj[prop];
    }

    // Get the number of products; an alias of products.length
    if (prop === 'number') {
      return obj.length;
    }

    let result;
    const types = {};

    for (const product of obj) {
      if (product.name === prop) {
        result = product;
      }
      if (types[product.type]) {
        types[product.type].push(product);
      } else {
        types[product.type] = [product];
      }
    }

    // Get a product by name
    if (result) {
      return result;
    }

    // Get products by type
    if (prop in types) {
      return types[prop];
    }

    // Get product types
    if (prop === 'types') {
      return Object.keys(types);
    }

    return undefined;
  }
});

console.log(products[0]);          // { name: 'Firefox', type: 'browser' }
console.log(products['Firefox']);  // { name: 'Firefox', type: 'browser' }
console.log(products['Chrome']);   // undefined
console.log(products.browser);     // [{ name: 'Firefox', type: 'browser' }, { name: 'SeaMonkey', type: 'browser' }]
console.log(products.types);       // ['browser', 'mailer']
console.log(products.number);      // 3

Enter fullscreen mode Exit fullscreen mode

以上代码片段来自Mozilla 文档,展示了如何使用代理以最优方式查找对象数组中的对象。

还有许多其他实际用例可以利用其强大的功能Proxy来更好地维护代码并使其更简洁。

PS:这些是我每天都会用到的几个技巧,还有一些其他的,比如DOM操作、属性转发等等。你可以在这里查看。

希望这能帮到你。干杯🍻

文章来源:https://dev.to/jeevankishore/real-world-use-cases-of-object-proxies-3d87