news 2026/5/27 17:23:49

【Vue】08 Vue技术——回顾 Vue 中的 `Object.defineProperty` 方法的使用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Vue】08 Vue技术——回顾 Vue 中的 `Object.defineProperty` 方法的使用

文章目录

    • 1. 引言
    • 2. 完整示例代码(含原始注释)
    • 3. 代码结构与变量初始化
      • 3.1 外部变量 `number`
      • 3.2 基础对象 `person`
    • 4. `Object.defineProperty` 的完整配置解析
      • 4.1 被注释掉的数据描述符(Data Descriptor)
      • 4.2 被注释掉的旧式 getter 写法
      • 4.3 实际启用的 getter
      • 4.4 实际启用的 setter
    • 5. 最终日志输出与行为验证
      • 5.1 控制台初始输出
      • 5.2 手动测试 getter/setter(在控制台执行)
        • 测试 1:读取 `age`
        • 测试 2:修改 `age`
        • 测试 3:再次读取
    • 6. 与 Vue 2 响应式系统的关联
    • 7. 总结

1. 引言

在 Vue 2 的响应式系统实现中,Object.defineProperty是核心机制之一。虽然 Vue 3 已经转向使用更强大的Proxy,但理解Object.defineProperty对于掌握 Vue 响应式原理、调试旧项目以及深入 JavaScript 对象属性控制仍具有重要意义。本文将结合一段包含详细注释的示例代码,逐行解析其设计思路、配置选项含义以及运行行为,并展示控制台中的实际输出结果。


2. 完整示例代码(含原始注释)

<!DOCTYPEhtml><html><head><metacharset="UTF-8"/><title>回顾Object.defineProperty方法</title><!-- 引入Vue --><!-- <script type="text/javascript" src="../js/vue.js"></script> --></head><body><scripttype="text/javascript">letnumber=18letperson={name:'张三',sex:'男',}Object.defineProperty(person,'age',{// value:18,// enumerable:true, // 控制属性是否可以枚举,默认值为false// writable:true, // 控制属性是否可以被修改,默认值是false// configurable:true, // 控制属性是否可以被删除,默认值是false// 当有人读取age的属性时,get函数(getter)就会被调用,且返回值就是age的值// get:function(){// //return 'hello'// console.log('有人读取age属性了')// return number// }get(){//return 'hello'console.log('有人读取age属性了')returnnumber},// 当有人修改person的age的属性时,set函数(setter)就会被调用,且会受到修改的具体值set(value){console.log('有人修改了age属性,且值是:',value)number=value}})console.log(person)</script></body></html>

这段代码不仅实现了age属性的响应式定义,还通过大量注释说明了Object.defineProperty的各种配置项及其作用。下面我们将逐部分讲解这些注释内容和实际代码逻辑


3. 代码结构与变量初始化

3.1 外部变量number

letnumber=18
  • 这是一个闭包变量,用于存储age属性的真实值。
  • 使用外部变量而非直接在对象上存值,是为了配合 getter/setter 实现“拦截”逻辑。
  • 在 Vue 2 中,类似地,每个响应式属性背后都有一个内部存储(如_data.age),并通过 getter/setter 暴露给用户。

3.2 基础对象person

letperson={name:'张三',sex:'男',}
  • 初始对象仅包含两个普通属性:namesex
  • 后续将通过Object.defineProperty动态添加age属性,而非直接赋值(如person.age = 18)。

4.Object.defineProperty的完整配置解析

调用:

Object.defineProperty(person,'age',{/* descriptor */})

目标是为person对象定义一个名为'age'的新属性,其行为由描述符(descriptor)控制。

4.1 被注释掉的数据描述符(Data Descriptor)

// value:18,// enumerable:true, // 控制属性是否可以枚举,默认值为false// writable:true, // 控制属性是否可以被修改,默认值是false// configurable:true, // 控制属性是否可以被删除,默认值是false

这些是数据描述符的典型配置项,适用于直接定义静态值的属性:

  • value:属性的值。若使用此选项,则不能同时使用get/set
  • enumerable:是否可枚举。
    • 若为false(默认),则该属性不会出现在for...in循环、Object.keys()JSON.stringify()中。
    • 示例中未显式设置,因此age默认不可枚举。
  • writable:是否可写。
    • 若为false,则person.age = 20会静默失败(严格模式下抛错)。
  • configurable:是否可配置。
    • 若为false,则无法删除该属性,也无法再次修改其描述符(包括转为 getter/setter)。

关键点:一旦使用get/set(存取描述符),就不能再使用valuewritable,否则会报错。

4.2 被注释掉的旧式 getter 写法

// get:function(){// //return 'hello'// console.log('有人读取age属性了')// return number// }

这是 ES5 风格的函数写法,功能与下方的简写形式完全一致。现代开发中通常使用 ES6 的方法简写:

get(){console.log('有人读取age属性了')returnnumber}

两者等价,后者更简洁。

4.3 实际启用的 getter

get(){//return 'hello'console.log('有人读取age属性了')returnnumber}
  • 当代码执行person.age时,自动调用此函数。
  • 函数体中:
    • console.log(...)用于追踪访问行为(模拟 Vue 的依赖收集日志)。
    • return number返回真实存储的值。
    • 注释掉的//return 'hello'表明:你可以返回任意值,不一定要与原变量一致(可用于计算属性或格式化)。

4.4 实际启用的 setter

set(value){console.log('有人修改了age属性,且值是:',value)number=value}
  • 当执行person.age = newValue时,自动调用此函数,value即为传入的新值。
  • 函数体中:
    • 打印日志,记录修改行为(模拟 Vue 的派发更新通知)。
    • 将新值赋给闭包变量number,确保后续get能返回最新值。
  • 注意:setter 不返回任何值,其作用是副作用(side effect)。

5. 最终日志输出与行为验证

console.log(person)

5.1 控制台初始输出

运行页面后,控制台首先显示:

{ name: "张三", sex: "男" }
  • age未显示,因为其enumerable默认为false
  • 此时未触发getset,因为只是打印对象引用,未实际访问age

5.2 手动测试 getter/setter(在控制台执行)

测试 1:读取age
person.age

输出

有人读取age属性了 18

→ 触发get,返回number的当前值。

测试 2:修改age
person.age=30

输出

有人修改了age属性,且值是: 30

→ 触发set,将number更新为 30。

测试 3:再次读取
person.age

输出

有人读取age属性了 30

get返回更新后的值。


6. 与 Vue 2 响应式系统的关联

上述代码正是 Vue 2 实现响应式的核心简化版:

  • get→ 收集依赖(如 Watcher)
  • set→ 通知依赖更新(触发 re-render)
  • 闭包变量number→ 对应组件实例的_data.age
  • 不可枚举性→ 避免干扰普通属性遍历

这也解释了为什么 Vue 2 无法检测到:

  • 新增属性(需Vue.set
  • 删除属性(需Vue.delete
  • 数组索引直接赋值(因无法拦截)

因为Object.defineProperty只能拦截已知属性的读写。


7. 总结

本文不仅展示了Object.defineProperty的基本用法,更完整解读了原始代码中的每一处注释和设计意图

  • 数据描述符(value,writable,enumerable,configurable)的作用与限制;
  • 存取描述符(get/set)如何实现属性拦截;
  • 闭包变量在状态管理中的关键角色;
  • 控制台输出的行为逻辑及测试方法;
  • 与 Vue 2 响应式原理的直接对应关系。

通过这种“带注释的代码 + 逐行讲解”的方式,我们不仅能学会如何使用Object.defineProperty,更能理解其在框架底层中的工程价值。这对于深入前端原理、排查响应式 bug、乃至面试进阶都具有重要意义。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/21 19:54:57

电商系统中的Python排序实战:从基础到高级

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个电商商品排序系统&#xff0c;功能包括&#xff1a;1. 基础价格排序 2. 多条件排序&#xff08;销量评分价格&#xff09;3. 自定义排序规则&#xff08;如促销商品优先&a…

作者头像 李华
网站建设 2026/5/3 13:13:06

VSCode调试模式下敏感数据保护方案(企业级安全实践曝光)

第一章&#xff1a;VSCode调试模式下敏感数据保护方案&#xff08;企业级安全实践曝光&#xff09;在企业级开发环境中&#xff0c;VSCode作为主流代码编辑器&#xff0c;其调试功能极大提升了开发效率。然而&#xff0c;调试过程中变量值的自动显示可能暴露数据库凭证、API密钥…

作者头像 李华
网站建设 2026/5/26 10:32:29

CYGWIN实战:Windows下的Linux开发环境搭建指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 在快马平台生成一个CYGWIN环境配置脚本&#xff0c;自动安装GCC、Make、Git等开发工具&#xff0c;并设置环境变量。脚本需包含安装进度显示、依赖检查功能&#xff0c;支持自定义…

作者头像 李华
网站建设 2026/5/20 13:37:11

【MCP远程考试必看】:考前72小时倒计时 checklist 全公开

第一章&#xff1a;MCP远程考试概述Microsoft Certified Professional&#xff08;MCP&#xff09;远程考试为IT从业者提供了灵活、便捷的认证路径。考生无需前往指定考点&#xff0c;只需在符合要求的环境中通过官方授权平台完成身份验证与考试流程&#xff0c;即可获得微软认…

作者头像 李华
网站建设 2026/5/21 9:05:23

游戏开发者必看:正确处理Visual C++运行库依赖

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个游戏安装包示例项目&#xff0c;展示如何正确打包和部署Visual C 2015-2022 Redistributable (x64)。要求&#xff1a;1) 使用Inno Setup或NSIS制作安装程序&#xff1b;2…

作者头像 李华
网站建设 2026/5/3 12:04:59

用FREE-H技术快速构建智能客服原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 使用FREE-H技术开发一个智能客服系统原型。系统应支持自然语言处理&#xff0c;自动回答用户问题&#xff0c;并记录交互数据以供分析。快速验证核心功能&#xff0c;便于后续迭代…

作者头像 李华