← JavaScript 代理 没有下一篇了 →

JavaScript Proxy get用法

原创 2026-03-24 JavaScript 已有人查阅

JavaScript Proxy 的 get :不只是拦截读取

在 JavaScript 的进阶之路上,Proxy 是一个绕不开的强大特性。它允许我们创建一个对象的代理,从而拦截并重新定义该对象的基本操作。今天,咱们就来深入聊聊 Proxy 中最常用的一个方法 —— get

很多人对 get 的理解仅仅停留在“拦截属性读取”这个层面。但真正用好它,能让你在数据校验、日志记录、动态属性计算等方面玩出很多花样。

get 方法是什么?

简单来说,get 是当你试图访问一个对象的属性时,会被调用的一个函数。它就像是你为对象的“读取操作”设置的一道关卡,每次有人来拿东西,都得先过你这关。

语法结构

get: function(target, property, receiver) {
    // 你的自定义逻辑
    return something;
}

这三个参数是理解整个机制的关键:

  • target:原始的目标对象,也就是被代理的那个对象。

  • property:你要获取的属性名(key)。

  • receiver:这个参数稍有些抽象,它通常是代理对象本身,或者任何继承了该代理的对象。在大多数日常使用中,你可以先简单理解为 receiver 就是当前的 proxy 实例。

从代码号的角度看 get 的核心价值

很多刚接触的同学会问:“我直接访问原对象不是更简单吗?为什么非要绕个圈子用 Proxy 和 get?”

这就是我要分享的一个个人经验了。直接访问对象就像是你直接去仓库里拿货,没有任何记录,也没有任何加工。而 get ,则是在仓库门口安排了一个管理员。你可以让这个管理员做很多事情:

  1. 数据加工:原对象存的是原始值,你可以返回一个计算后的值。

  2. 权限验证:在返回数据前,先检查当前操作是否有权限。

  3. 错误处理:当访问一个不存在的属性时,返回一个友好的提示,而不是 undefined

  4. 记录日志:追踪哪些属性被访问了,这对于调试和分析非常有帮助。

示例 1:对数据进行实时计算与格式化

这个示例中,我们创建一个 user 对象的代理。原对象存的是基本数据,但通过 get ,我们可以在读取时动态地组合和格式化数据。这是 get 非常典型的应用场景。

// 代码号:创建一个用户对象,并为其添加智能读取功能
const user = {
    firstName: '张',
    lastName: '三',
    age: 28
};

const userProxy = new Proxy(user, {
    get: function(target, property, receiver) {
        // 自定义属性 'fullName',它并不真实存在于 target 中
        if (property === 'fullName') {
            return `${target.firstName}${target.lastName}`;
        }
        // 对于 'info' 属性,返回一个包含年龄的提示信息
        if (property === 'info') {
            return `${target.firstName}${target.lastName},年龄 ${target.age} 岁`;
        }
        // 对于其他属性,直接返回原始值
        return target[property];
    }
});

// 输出:张三
console.log(userProxy.fullName);
// 输出:张三,年龄 28 岁
console.log(userProxy.info);
// 输出:28
console.log(userProxy.age);

在这个示例中,我们为 userProxy 添加了两个虚拟属性 fullName 和 info,它们在被读取时才动态生成。原对象 user 并未被修改,却实现了更强大的功能。

示例 2:实现属性访问的“保护”与“日志”

下面这个例子,我们展示如何利用 get 实现一个简单的权限控制和访问日志。这在开发中,比如构建一个数据模型层时,非常有用。你可以追踪哪些数据被前端读取了。

// 代码号:为敏感数据创建一个带日志功能的代理
const sensitiveData = {
    apiKey: '12345-abcde',
    publicName: '代码号公开服务'
};

const protectedProxy = new Proxy(sensitiveData, {
    get: function(target, property, receiver) {
        // 核心知识点:对 'apiKey' 属性进行访问保护
        if (property === 'apiKey') {
            // 个人见解:实际项目中这里可以换成更复杂的权限校验
            console.warn(`警告:正在尝试访问敏感属性 ${property}!`);
            return '******'; // 返回一个掩码,而不是真实值
        }
        
        // 记录所有非敏感属性的访问日志
        console.log(`[日志] 属性 "${property}" 被读取。时间:2026年`);
        
        // 对于普通属性,正常返回
        return target[property];
    }
});

// 尝试访问普通属性,会记录日志
console.log(protectedProxy.publicName);
// 尝试访问敏感属性,会发出警告并返回掩码
console.log(protectedProxy.apiKey);

示例 3:处理未定义的属性

get 可以优雅地处理那些不存在的属性,避免程序因为访问 undefined 而报错或产生难以排查的 bug。

// 代码号:为对象设置一个“默认行为”来处理未知属性
const config = {
    theme: 'dark',
    language: 'zh-CN'
};

const configProxy = new Proxy(config, {
    get: function(target, property, receiver) {
        // 如果属性存在于原对象中,直接返回
        if (property in target) {
            return target[property];
        }
        // 如果属性不存在,返回一个默认值
        console.warn(`配置项 "${property}" 未定义,返回默认值。`);
        return 'default';
    }
});

console.log(configProxy.theme);    // 输出: dark
console.log(configProxy.fontSize); // 输出: default,并打印警告

本节课程知识要点

  1. 明确 get 的三个参数:理解 target (目标对象)、property (属性名) 和 receiver (代理对象) 各自的作用是编写正确逻辑的基础。

  2. 动态属性计算get 方法内部可以根据 property 参数,返回一个由原始数据计算得出的值,从而实现虚拟属性的效果。

  3. 访问控制与副作用:在返回数据前,可以加入任何逻辑,比如权限验证 (if 判断)、日志记录 (console.log)、数据格式化等,这是 get 最核心的“代理”价值。

  4. 性能考量:虽然 get 非常强大,但为每一个属性访问都增加一层代理,会带来微小的性能开销。在非高频操作的热路径上,可以放心使用;但如果是在循环或动画中频繁读取属性,需要权衡利弊。

  5. 与 Reflect 的结合:在的复杂项目中,常常会将 get 与 Reflect.get() 配合使用,以保持默认行为的正确性,尤其是在处理继承关系时。这是一个更高级的实践,可以在你熟悉基础后深入学习。

希望今天的分享能让你对 Proxy 的 get 有一个更立体、更实用的认识。编程的魅力就在于,当我们能精确地控制数据的“来龙去脉”时,就能创造出更健壮、更易维护的系统。

← JavaScript 代理 没有下一篇了 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号