导读:本期聚焦于小伙伴创作的《JavaScript中如何使用Object.defineProperty?详解属性描述符与实战应用》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《JavaScript中如何使用Object.defineProperty?详解属性描述符与实战应用》有用,将其分享出去将是对创作者最好的鼓励。

JavaScript中Object.defineProperty的使用详解

在JavaScript开发中,我们经常需要对对象的属性进行更精细的控制,比如让属性不可被修改、不可被枚举,或者在属性被访问、修改时执行自定义逻辑。这时候就可以用到Object.defineProperty方法,它是JavaScript中用于定义或修改对象属性的核心API,允许我们设置属性的各种特性。

Object.defineProperty的基本语法

该方法接收三个参数,语法结构如下:

Object.defineProperty(obj, prop, descriptor)

三个参数的含义分别是:

  • obj:要在其上定义属性的目标对象
  • prop:要定义或修改的属性的名称,类型为字符串或Symbol
  • descriptor:属性描述符对象,用于定义该属性的具体特性

方法执行后会返回修改后的目标对象obj。

属性描述符的分类

属性描述符分为两类:数据描述符存取描述符,同一时间一个属性只能使用其中一种类型的描述符,不能混合使用。

数据描述符

数据描述符用于定义普通的属性值,包含以下可选字段:

  • value:属性的值,默认为undefined
  • writable:布尔值,表示属性的值是否可以被修改,默认为false
  • enumerable:布尔值,表示属性是否可以通过for...in循环或Object.keys()枚举,默认为false
  • configurable:布尔值,表示属性是否可以被删除,以及除value和writable外的其他特性是否可以被修改,默认为false

下面是一个使用数据描述符定义属性的示例:

// 定义一个空对象
const user = {};

// 使用Object.defineProperty给user对象添加name属性
Object.defineProperty(user, 'name', {
  value: '张三',       // 属性值为张三
  writable: false,     // 属性不可修改
  enumerable: true,    // 属性可枚举
  configurable: false  // 属性不可删除,特性不可修改
});

console.log(user.name); // 输出:张三

// 尝试修改name属性
user.name = '李四';
console.log(user.name); // 输出:张三,修改无效

// 尝试删除name属性
delete user.name;
console.log(user.name); // 输出:张三,删除无效

// 遍历对象的可枚举属性
console.log(Object.keys(user)); // 输出:['name']

存取描述符

存取描述符通过getter和setter函数来获取或设置属性的值,包含以下可选字段:

  • get:一个函数,当访问该属性时会被调用,返回值作为属性的值,默认为undefined
  • set:一个函数,当修改该属性时会被调用,接收修改后的值作为参数,默认为undefined
  • enumerable:和数数据描述符的含义一致,控制属性是否可枚举
  • configurable:和数据描述符的含义一致,控制属性是否可配置

注意:存取描述符不能和数据描述符的value、writable字段同时存在,否则会报错。

下面是一个使用存取描述符实现属性代理的示例:

const person = {
  _age: 18 // 下划线开头的属性通常表示私有属性,不直接访问
};

// 使用存取描述符定义age属性
Object.defineProperty(person, 'age', {
  enumerable: true,
  configurable: true,
  get() {
    console.log('正在访问age属性');
    return this._age;
  },
  set(newVal) {
    console.log('正在修改age属性,新值为:' + newVal);
    if (typeof newVal !== 'number' || newVal < 0 || newVal > 150) {
      throw new Error('年龄必须是0到150之间的数字');
    }
    this._age = newVal;
  }
});

console.log(person.age); // 输出:正在访问age属性  18
person.age = 20; // 输出:正在修改age属性,新值为:20
console.log(person.age); // 输出:正在访问age属性  20

// 尝试设置非法值
try {
  person.age = '二十';
} catch (e) {
  console.log(e.message); // 输出:年龄必须是0到150之间的数字
}

批量定义属性:Object.defineProperties

如果需要同时给对象定义多个属性,可以使用Object.defineProperties方法,它接收一个对象和一个属性描述符映射对象作为参数:

const student = {};

Object.defineProperties(student, {
  name: {
    value: '小明',
    enumerable: true
  },
  score: {
    value: 90,
    enumerable: true,
    writable: true
  },
  grade: {
    get() {
      if (this.score >= 90) return 'A';
      if (this.score >= 80) return 'B';
      if (this.score >= 60) return 'C';
      return 'D';
    },
    enumerable: true
  }
});

console.log(student.name); // 输出:小明
console.log(student.score); // 输出:90
console.log(student.grade); // 输出:A

student.score = 75;
console.log(student.grade); // 输出:C

实际应用场景

Object.defineProperty在前端开发中有很多常见的应用场景:

  • 实现Vue 2.x的响应式系统,通过劫持对象的getter和setter来追踪依赖、触发视图更新
  • 定义对象的只读属性,防止重要属性被意外修改
  • 实现属性的校验逻辑,在设置属性值时进行合法性检查
  • 隐藏对象的某些内部属性,避免被外部直接访问或枚举

需要注意的是,Object.defineProperty无法监听对象新增属性和数组索引变化,这也是Vue 2.x中需要使用$set方法添加新属性的原因。如果需要更全面的对象变化监听,在现代JavaScript环境中可以考虑使用Proxy API,它是对Object.defineProperty的能力补充和升级。

Object.defineProperty属性描述符数据描述符存取描述符JavaScript 本作品最后修改时间:2026-05-22 14:06:39

免责声明:网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。