myfreax

JavaScript proxy 代理

JavaScript 代理是一个对象,它包装另一个对象(目标)并拦截目标对象的基本操作。这些基本操作可以是属性查找、赋值、枚举、函数调用等

JavaScript proxy 代理
JavaScript 代理对象

在本教程中,您将了解 ES6 的 JavaScript 代理对象。

JavaScript 代理对象

JavaScript 代理是一个对象,它包装另一个对象(目标)并拦截目标对象的基本操作。这些基本操作可以是属性查找、赋值、枚举、函数调用等。

创建代理对象

要创建新的代理对象,请使用以下语法:

let proxy = new Proxy(target, handler);

在这个语法中:

  • target – 是一个要包装的对象。
  • handler – 是一个对象,包含控制目标对象内部的方法。

一个简单的代理示例

首先,定义一个名为 user 的对象:

const user = {
    firstName: 'John',
    lastName: 'Doe',
    email: 'john.doe@example.com',
}

其次,定义一个 handler 对象:

const handler = {
    get(target, property) {
        console.log(`Property ${property} has been read.`);
        return target[property];
    }
}

三、创建 proxy 对象:

const proxyUser = new Proxy(user, handler);

proxyUser 对象使用 user 对象来存储数据。proxyUser 可以访问 user 对象的所有属性。

四、通过 proxyUser 对象 user 访问对象的firstNamelastName 属性:

console.log(proxyUser.firstName);
console.log(proxyUser.lastName);

输出:

Property firstName has been read.
John
Property lastName has been read.
Doe

当通过 proxyUser 对象访问 user 对象的属性时,会调用 handler 对象的 get() 方法。

第五,如果修改原始 user 对象,proxyUser 对象也会获得修改后的属性值:

user.firstName = 'Jane';
console.log(proxyUser.firstName);

输出:

Property firstName has been read.
Jane

类似地,proxyUser 对象的更改将反映在原始的 user 对象中:

proxyUser.lastName = 'William';
console.log(user.lastName);

输出:

William    

代理捕捉器

get 捕捉器

当通过代理对象访问 target 对象的属性时,会触发 get 捕捉器。在前面的示例中,当 proxyUser 对象访问 user 对象的属性时,会打印一条消息。

通常,您可以在访问属性时在 get 捕捉器编写自定义逻辑。例如,您可以使用 get 捕捉器来定义目标对象的计算属性。

下面的 user 对象没有 fullName 属性,您可以使用 get 捕捉器根据 firstNamelastName 属性创建属性:

const user = {
    firstName: 'John',
    lastName: 'Doe'
}

const handler = {
    get(target, property) {
        return property === 'fullName' ?
            `${target.firstName} ${target.lastName}` :
            target[property];
    }
};

const proxyUser = new Proxy(user, handler);

console.log(proxyUser.fullName);

输出:

John Doe

set 捕捉器

当设置 target 对象的属性时, set 捕捉器可以控制其行为。

假设用户的 age 必须大于 18。为了强制执行此约束,您可以通过自定义 set 捕捉器定义其行为,如下所示:

const user = {
    firstName: 'John',
    lastName: 'Doe',
    age: 20
}

const handler = {
    set(target, property, value) {
        if (property === 'age') {
            if (typeof value !== 'number') {
                throw new Error('Age must be a number.');
            }
            if (value < 18) {
                throw new Error('The user must be 18 or older.')
            }
        }
        target[property] = value;
    }
};

const proxyUser = new Proxy(user, handler);

apply 捕捉器

handler.apply() 方法是函数调用的捕捉器。语法如下:

let proxy = new Proxy(target, {
    apply: function(target, thisArg, args) {
        //...
    }
});

以下是示例:

const user = {
    firstName: 'John',
    lastName: 'Doe'
}

const getFullName = function (user) {
    return `${user.firstName} ${user.lastName}`;
}


const getFullNameProxy = new Proxy(getFullName, {
    apply(target, thisArg, args) {
        return target(...args).toUpperCase();
    }
});

console.log(getFullNameProxy(user)); // 

输出

JOHN DOE

除了上述捕捉器,你也还可以使用以下捕捉器实现你所需的功能。

  • construct – 捕获 new 关键词的初始化
  • getPrototypeOf – 捕获内部  [[GetPrototypeOf]] 调用
  • setPrototypeOf – 捕获 Object.setPrototypeOf 调用
  • isExtensible– 捕获 Object.isExtensible 调用
  • preventExtensions– 捕获 Object.preventExtensions 调用
  • getOwnPropertyDescriptor– 捕获 Object.getOwnPropertyDescriptor 调用

结论

在本教程中,您了解用于JavaScript 代理,它用于包装另一个对象(目标)并拦截目标对象的基本操作。

内容导航