ES6 prox的作用

78 阅读2分钟

ES6 prox的作用

ES6 引入了 Proxy(代理),它是一种元编程特性,允许你拦截并自定义对象的基本操作(如属性查找、赋值、枚举等)。Proxy 的作用是为对象创建一个代理层,通过这个代理层可以控制对目标对象的访问和操作。

以下是 Proxy 的主要作用和应用场景:

  1. 基本用法

Proxy 的基本语法是:

const proxy = new Proxy(target, handler);
  • target:目标对象,即需要被代理的对象。
  • handler:一个对象,定义了拦截操作的“陷阱”(trap)函数。

示例:

const target = {
    name: 'Alice',
    age: 25
};

const handler = {
    get(target, prop) {
        if (prop === 'age') {
            return target[prop] + ' years old';
        }
        return target[prop];
    }
};

const proxy = new Proxy(target, handler);

console.log(proxy.name); // Alice
console.log(proxy.age); // 25 years old
  1. 常用的陷阱函数

handler 对象中可以定义多种陷阱函数来拦截不同的操作:

陷阱函数拦截的操作
get(target, prop)读取属性时调用
set(target, prop, value)设置属性时调用
has(target, prop)使用in 操作符时调用
deleteProperty(target, prop)使用delete 操作符时调用
apply(target, thisArg, args)调用函数时调用(用于代理函数)
construct(target, args)使用new 操作符时调用(用于代理构造函数)
ownKeys(target)获取对象自身属性键时调用

示例:拦截属性读取和设置

const target = {
    name: 'Alice',
    age: 25
};

const handler = {
    get(target, prop) {
        console.log(`Reading property: ${prop}`);
        return target[prop];
    },
    set(target, prop, value) {
        console.log(`Setting property: ${prop} = ${value}`);
        target[prop] = value;
        return true; // 表示设置成功
    }
};

const proxy = new Proxy(target, handler);

proxy.name; // 输出: Reading property: name
proxy.age = 30; // 输出: Setting property: age = 30
  1. 验证和过滤

Proxy 可以用于验证或过滤对目标对象的操作,例如:

  • 验证属性值是否符合要求。
  • 防止某些属性被修改或删除。

示例:验证属性值

const target = {
    age: 25
};

const handler = {
    set(target, prop, value) {
        if (prop === 'age' && typeof value !== 'number') {
            throw new TypeError('Age must be a number');
        }
        target[prop] = value;
        return true;
    }
};

const proxy = new Proxy(target, handler);

proxy.age = 30; // 正常
proxy.age = '30'; // 抛出错误: Age must be a number
  1. 函数代理

Proxy 不仅可以代理对象,还可以代理函数。通过 apply 陷阱函数,可以拦截函数的调用。

示例:拦截函数调用

function sum(a, b) {
    return a + b;
}

const handler = {
    apply(target, thisArg, args) {
        console.log(`Calling function with arguments: ${args}`);
        return target(...args);
    }
};

const proxy = new Proxy(sum, handler);

console.log(proxy(1, 2)); // 输出: Calling function with arguments: 1,2
                          // 输出: 3
  1. 构造函数代理

通过 construct 陷阱函数,可以拦截 new 操作符对构造函数的调用。

示例:拦截构造函数调用

class Person {
    constructor(name) {
        this.name = name;
    }
}

const handler = {
    construct(target, args) {
        console.log(`Creating instance with arguments: ${args}`);
        return new target(...args);
    }
};

const ProxyPerson = new Proxy(Person, handler);

const alice = new ProxyPerson('Alice'); // 输出: Creating instance with arguments: Alice
console.log(alice.name); // Alice
  1. 隐藏私有属性

Proxy 可以用于隐藏对象的私有属性,使其无法被直接访问。

示例:隐藏私有属性

const target = {
    name: 'Alice',
    _password: '123456'
};

const handler = {
    get(target, prop) {
        if (prop.startsWith('_')) {
            throw new Error('Access denied');
        }
        return target[prop];
    },
    set(target, prop, value) {
        if (prop.startsWith('_')) {
            throw new Error('Access denied');
        }
        target[prop] = value;
        return true;
    }
};

const proxy = new Proxy(target, handler);

console.log(proxy.name); // Alice
console.log(proxy._password); // 抛出错误: Access denied
  1. 应用场景
  • 数据验证:拦截属性赋值操作,验证数据是否符合要求。
  • 日志记录:记录对象的读写操作。
  • 缓存:拦截函数调用,实现缓存机制。
  • 隐藏私有属性:防止私有属性被直接访问。
  • 观察者模式:监听对象的变化并触发回调。

示例:观察者模式

const target = {
    name: 'Alice'
};

const observers = [];

const handler = {
    set(target, prop, value) {
        target[prop] = value;
        observers.forEach(observer => observer(prop, value));
        return true;
    }
};

const proxy = new Proxy(target, handler);

observers.push((prop, value) => {
    console.log(`Property ${prop} changed to ${value}`);
});

proxy.name = 'Bob'; // 输出: Property name changed to Bob
  1. Reflect 结合使用

Reflect 是 ES6 引入的一个内置对象,提供了与 Proxy 陷阱函数一一对应的方法。通常可以将 ProxyReflect 结合使用,以简化代码。

示例:

const target = {
    name: 'Alice'
};

const handler = {
    get(target, prop) {
        console.log(`Reading property: ${prop}`);
        return Reflect.get(target, prop);
    },
    set(target, prop, value) {
        console.log(`Setting property: ${prop} = ${value}`);
        return Reflect.set(target, prop, value);
    }
};

const proxy = new Proxy(target, handler);

proxy.name; // 输出: Reading property: name
proxy.name = 'Bob'; // 输出: Setting property: name = Bob

总结

Proxy 是 ES6 引入的一种强大的元编程工具,允许你拦截并自定义对象的基本操作。它的主要作用包括数据验证、日志记录、缓存、隐藏私有属性等。通过 Proxy,你可以更灵活地控制对象的行为,实现更高级的功能。

更多vue相关插件及后台管理模板可访问vue admin reference,代码详情请访问github