JavaScript 对象管家 Proxy

目录
  • 正文
    • 语法
    • 对象方法
    • 属性获取器/设置器
    • 函数方法
    • 捕捉器
    • get
    • set
    • 应用场景
    • 验证和过滤
    • 缓存
    • 监听属性变化
    • 防止误操作
    • 虚拟化
  • 总结

正文

JavaScript 在 ES6 中,引入了一个新的对象类型 Proxy,它可以用来代理另一个对象,并可以在代理过程中拦截、覆盖和定制对象的操作。Proxy 对象封装另一个对象并充当中间人,其提供了一个捕捉器函数,可以在代理对象上拦截所有的操作,包括访问属性、赋值属性、函数调用等等。通过拦截这些操作,可以对代理对象进行定制和控制。

在开始介绍 Proxy 对象前先了解 3 个术语:

  • target 目标对象:要代理的对象或函数。
  • handler 处理程序:对代理的对象或函数执行某些操作的函数。
  • traps 捕捉器:这些是一些用于处理目标的函数。单击此处阅读有关陷阱的更多信息。

语法

Proxy 对象的基本语法如下:

new Proxy(target, handler);

其中,target 是被代理的目标对象,handler 是一个对象,它包含了一些捕捉器函数,用来拦截代理对象的操作。

下面是一些常见的拦截操作和对应的捕捉器函数:

对象方法

  • getPrototypeOf()Object.getPrototypeOf 方法的捕捉器。
  • setPrototypeOf()Object.setPrototypeOf 方法的捕捉器。
  • isExtensible()Object.isExtensible 方法的捕捉器。
  • preventExtensions()Object.preventExtensions 方法的捕捉器。
  • getOwnPropertyDescriptor()Object.getOwnPropertyDescriptor 方法的捕捉器。
  • handler.defineProperty()Object.defineProperty 方法的捕捉器。

属性获取器/设置器

  • get(target, propKey, receiver):拦截对象的读取属性操作,返回属性值。
  • set(target, propKey, value, receiver):拦截对象的设置属性操作,返回一个布尔值表示是否设置成功。
  • has(target, propKey):拦截对象的 in 操作符,返回一个布尔值表示对象是否包含该属性。
  • deleteProperty(target, propKey):拦截对象的 delete 操作符,返回一个布尔值表示是否删除成功。
  • ownKeys()Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器

函数方法

如果目标对象是一个函数,可以使用下面 2 个捕捉器。

  • apply(target, thisArg, args):拦截函数的调用操作,返回调用结果。
  • construct(target, args, newTarget):拦截 new 操作符,返回一个对象。

Proxy 在目标对象周围创建一个不可检测的屏障,将所有操作重定向到处理程序对象。如果发送一个空的 handler ,代理只是原始对象的一个空包装器。

const author = {
    name: "Quintion",
    age: 36,
};
const proxyAuthor = new Proxy(author, {});
console.log(author.name); // Quintion
console.log(proxyAuthor.name); // Quintion

为了赋予代理意义,需要向处理程序添加一些操作方法。

捕捉器

每当与一个对象交互时,都在调用一个内部方法。代理允许使用捕捉器拦截给定内部方法的执行。

因此,当运行 author.name 时,告诉 JavaScript 引擎调用内部 [[GET]] 方法来检索 name 属性。当运行 proxyAuthor.name 时,get 捕捉器会调用处理程序中定义的 get() 函数来执行,然后再将调用发送到原始对象。

get

get() 方法有两个必需的参数:

  • target — 传递给代理的对象。
  • property — 访问的属性的名称。

要自定义代理,在处理程序对象上定义函数。下面定义了 get 方法来记录访问:

const handler = {
    get(target, property) {
        console.log(`捕捉器 GET:${property}`);
        return target[property];
    },
};

为了让调用通过,捕捉器 get 返回 target[property]。使用方式如下:

const author = {
    name: "Quintion",
    age: 36,
};
const handler = {
    get(target, property) {
        console.log(`捕捉器 GET[${property}]`);
        return target[property];
    },
};
const proxyAuthor = new Proxy(author, handler);
console.log(proxyAuthor.name);

执行后,将打印以下内容:

捕捉器 GET[name]
Quintion

set

set 捕捉器用于给目标对象进行赋值操作,返回值是一个布尔值。set 捕捉器需要的参数如下:

  • target — 传递给代理的对象。
  • property — 将被设置的属性名或 Symbol。
  • value — 新的属性值
  • receiver — 最初被调用的对象。

下面通过 set 捕捉器验证年龄值的输入:

const handler = {
    set(target, property, value) {
        if (property === "age" && typeof value !== "number") {
            throw new TypeError("年龄必须是一个数字");
        }
        target[property] = value;
        return true;
    },
};

下面尝试将错误的类型值赋值给 age ,则会抛出错误:

const proxyAuthor = new Proxy(author, handler);
proxyAuthor.age = "young";
// 执行后抛出异常:throw new TypeError("年龄必须是一个数字");

set() 方法应该返回一个布尔值 true 用来表示赋值成功。 在严格模式下运行,并且返回一个假值或什么都不返回,则会抛出错误。

除了拦截对属性的读取和修改,Proxy 总共可以拦截 13 种操作。

应用场景

通过 Proxy 对象的特征,可以将其使用在下面这些场合:

验证和过滤

代理Proxy 用于拦截和验证对对象属性的访问。如,可以创建一个代理来检查用户输入的数据是否符合预期的格式,并拒绝不正确的数据。就如下面 age 属性赋值判断

缓存

代理Proxy 用于缓存对象的操作结果,以避免重复计算。如,可以创建一个代理来拦截对象的某些方法,并将结果存储在缓存中,以便将来使用。

下面是一个基于 Proxy 的缓存库的示例:

class Cache {
    constructor() {
        this.cache = new Map();
        this.proxy = new Proxy(this, {
            get(target, property) {
                if (property === "get") {
                    return (key) => {
                        return target.cache.get(key);
                    };
                }
                if (property === "set") {
                    return (key, value) => {
                        target.cache.set(key, value);
                    };
                }
                if (property === "has") {
                    return (key) => {
                        return target.cache.has(key);
                    };
                }
                if (property === "delete") {
                    return (key) => {
                        return target.cache.delete(key);
                    };
                }
            },
        });
    }
}

在上面的代码中,定义了一个 Cache 类,该类中包含一个内部的 Map 对象用于存储缓存数据,并且定义了一个 proxy 对象作为该类的代理。

proxy 对象的 get 方法中,根据传入的属性名返回相应的方法。如果属性名为 get,则返回一个可以获取缓存值的方法;如果属性名为 set,则返回一个可以设置缓存值的方法;如果属性名为 has,则返回一个可以判断是否存在缓存值的方法;如果属性名为 delete,则返回一个可以删除缓存值的方法。

下面是一个使用该缓存库的示例:

const cacheHelper = new Cache();
cacheHelper.set("foo", "bar");
console.log(cacheHelper.get("foo")); // "bar"
console.log(cacheHelper.has("foo")); // true
cacheHelper.delete("foo");
console.log(cacheHelper.get("foo")); // undefined
console.log(cacheHelper.has("foo")); // false

在上面的代码中,创建了一个 Cache 对象,并调用其 set 方法设置缓存值,然后调用其 get 方法获取缓存值,并调用其 has 方法判断缓存值是否存在,最后调用其 delete 方法删除缓存值。

监听属性变化

代理Proxy用于监视对象属性的变化,并在属性发生变化时触发其他操作。如,创建一个代理来监视对象属性的变化,并在属性发生变化时更新页面上的元素。

防止误操作

代理Proxy用于防止误操作,如,创建一个代理来拦截对象的某些方法,并在方法调用时检查一些条件,以确保方法只在正确的上下文中调用。

虚拟化

代理Proxy可以用于创建虚拟化对象。如,创建一个代理对象,用于代替某个对象的真实实现,并且在实际对象执行之前,对其进行修改或拦截。

总结

上面介绍了如何使用代理Proxy对象来监视对象,通过使用处理程序对象中的捕捉器方法向它们添加自定义行为,提供更高级的对象操作和控制功能,从而增强代码的可读性和可维护性。

以上就是JavaScript 对象管家 Proxy的详细内容,更多关于JavaScript对象Proxy的资料请关注我们其它相关文章!

(0)

相关推荐

  • JavaScript Proxy基本用法详解

    目录 1.语法 2.基本用法 3.可消除的Proxy 4.Vue为什么要用Proxy重构 5.Proxy与defineProperty的对比 1.语法 const proxy = new Proxy(target, handle); target,被代理的对象 handle,拦截规则 2.基本用法 const obj = {}; const proxy = new Proxy(obj, { // target 目标对象:propKey 属性名:receiver 实例本身: get: functi

  • JavaScript Object.defineProperty与proxy代理模式的使用详细分析

    目录 1. Object.defineProperty 2. Object.defineProperties 3. proxy 代理模式 总结 1. Object.defineProperty const obj = {}; Object.defineProperty(obj,prop,descript); 参数 obj 要定义属性的对象 prop 要定义的属性 descript 属性描述符 返回值:被传递给函数的对象 descript接收一个对象作为配置: writable 属性是否可写 默认

  • JS 中Proxy代理和 Reflect反射方法示例详解

    目录 正文 1.属性描述符 2.Reflect 3.Proxy 3.1 创建空代理 3.2 定义捕获器 3.3 捕获器不变式 3.4 可撤销代理 4.代理捕获器与反射方法 4.1 get() 4.2 set() 4.3 has() 4.4 deleteProperty() 4.5 apply() 4.6 construct() 正文 总所周知,Vue2 => Vue3 时,数据响应式方法从Object.defineProperty()方法变成了Proxy(),所以今天与大家 Proxy(代理)和

  • vue.config.js中devServer.proxy配置说明及配置正确不生效问题解决

    目录 proxy 配置确认.解析 原因 一 原因二 注意 详解 pathRewrite changeOrigin 总结 proxy 配置确认.解析 devServer: { https: true, // 开启https模式 // 配置服务器代理 proxy: { '/api': { // 匹配访问路径中含有 '/api' 的路径 target: 'http://localhost:3000/', // 测试地址.目标地址 changeOrigin: true, ws: true, // 是否开

  • JavaScript 对象管家 Proxy

    目录 正文 语法 对象方法 属性获取器/设置器 函数方法 捕捉器 get set 应用场景 验证和过滤 缓存 监听属性变化 防止误操作 虚拟化 总结 正文 JavaScript 在 ES6 中,引入了一个新的对象类型 Proxy,它可以用来代理另一个对象,并可以在代理过程中拦截.覆盖和定制对象的操作.Proxy 对象封装另一个对象并充当中间人,其提供了一个捕捉器函数,可以在代理对象上拦截所有的操作,包括访问属性.赋值属性.函数调用等等.通过拦截这些操作,可以对代理对象进行定制和控制. 在开始介绍

  • Javascript对象及Proxy工作原理详解

    正文 这一章其实算是javascript的科普文章,其实这本书的读者一般都不会是入门者,因此按道理说应该不需要再科普才对.但是作者依旧安排了这一章,证明就是这一章内容与我们以为的对象不一样. Javascript中一切皆对象 这一句话大家应该耳熟能详,对于常规的字面量对象,和new出来的对象,大家应该都能分辨 const str = '' const str2 = new String() const obj = {} const obj2 = Object.create() 但是根据ECMA,

  • JavaScript中的Proxy对象

    Js中Proxy对象 Proxy对象用于定义基本操作的自定义行为,例如属性查找.赋值.枚举.函数调用等. 语法 const proxy = new Proxy(target, handler); target: 要使用Proxy包装的目标对象,可以是任何类型的对象,包括原生数组,函数,甚至另一个代理. handler: 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理proxy的行为. 描述 Proxy用于修改某些操作的默认行为,也可以理解为在目标对象之前架设一层拦截,

  • 理解JavaScript中的Proxy 与 Reflection API

    一.创建 Proxy let target = {} let proxy = new Proxy(target, {}) proxy.name = "proxy" console.log(proxy.name) // proxy console.log(target.name) // proxy target.name = "target" console.log(proxy.name) // target console.log(target.name) // t

  • 枚举JavaScript对象的函数

    From: JavaEye.com 枚举JavaScript对象的函数: function iterator(obj) {  for (var property in obj) {  document.writeln("<p>" + property + " : " + obj[property] + "</p>");  } } 一个简单示例(test.js): function Employee () {   this.

  • 详解JavaScript对象类型

    JavaScrtip有六种数据类型,一种复杂的数据类型(引用类型),即Object对象类型,还有五种简单的数据类型(原始类型):Number.String.Boolean.Undefined和Null.其中,最核心的类型就是对象类型了.同时要注意,简单类型都是不可变的,而对象类型是可变的.  什么是对象  一个对象是一组简单数据类型(有时是引用数据类型)的无序列表,被存储为一系列的名-值对(name-value pairs).这个列表中的每一项被称为 属性(如果是函数则被称为 方法).  下面是

  • jQuery对象和Javascript对象之间转换的实例代码

    复制代码 代码如下: 以下是本人的一些分享,我热爱编程,希望能多交编程的爱好者,如果你也是其中一名,那么请加好友,大家关注一下,下面的文章是自己觉得一些有用的东西,留下来给自己当笔记,当然也希望能帮助到你,首先感谢你的阅读~! 如果我们在用jQuery作为客户端页面的脚本,时常都会涉及到jQuery对象和Javascript对象的相互转换.因为,DOM对象就是Javascript 固有的一些对象操作.DOM 对象能使用Javascript 固有的方法,但是不能使用 jQuery 里的方法.所以,

  • javascript对象小结

    距离某天还有天 javascript对象 var regExp=/\s\*/g; /*---------------string对象------------------*/ var str="this *is *test *string"; var sTxt=str.charAt(3); var aTxt=str.charCodeAt(3); var btxt=str.indexOf("s"); var cTxt=str.slice(0,4); var dTxt=s

  • 浅谈javascript对象模型和function对象

    javascript中,函数就是对象 复制代码 代码如下: <html> <head> <script type="text/javascript"> function add(number){     alert(number+20); } var add=function(number){ alert(number+20); } function add(number,number1){     alert(number+30); } var a

  • JavaScript对象封装的简单实现方法(3种方法)

    本文实例讲述了JavaScript对象封装的简单实现方法.分享给大家供大家参考,具体如下: Javascript在HTML中变得越来越强大,富客户端,HTML5中的WebGL等.但是我们书写Javascript的时候往往很随意,使用对象的封装是极好的.这里介绍Javascipt三种创建对象的方法. 1. 使用关键字new创建对象 function Person(name, age) { this.name = name; this.age = age; } var p = new Person(

随机推荐