Object.defineProperty介绍

半兽人 发表于: 2025-04-02   最后更新时间: 2025-04-02 15:29:12  
{{totalSubscript}} 订阅, 21 游览

Object.defineProperty 是 JavaScript 提供的 精确控制对象属性行为 的方法。它允许我们定义或修改对象的属性,并且可以设置该属性的 可写性(writable)、可配置性(configurable)和可枚举性(enumerable)

基本语法

Object.defineProperty(obj, prop, descriptor)
  • obj:要定义或修改属性的对象。
  • prop:要定义或修改的属性名称(字符串)。
  • descriptor:一个描述符对象,定义该属性的行为。

示例

let person = {}

Object.defineProperty(person, "name", {
  value: "Alice",
  writable: false, // 不可修改
  configurable: false, // 不可删除或重新定义
  enumerable: true // 可枚举
})

console.log(person.name) // "Alice"
person.name = "Bob" // 由于 writable: false,不会修改
console.log(person.name) // 仍然是 "Alice"

属性描述符(Descriptor)

描述符对象可以包含以下几个属性:

1. value(属性值)

  • 定义属性的默认值。
    Object.defineProperty(obj, "key", { value: "hello" })
    console.log(obj.key) // "hello"
    

2. writable(是否可写)

  • 默认 false,表示 不能修改该属性
    let obj = {}
    Object.defineProperty(obj, "x", {
    value: 10,
    writable: false
    })
    obj.x = 20 // 赋值失败
    console.log(obj.x) // 仍然是 10
    

3. enumerable(是否可枚举)

  • 默认 false,表示 该属性不会出现在 for...inObject.keys(obj) 结果中
    let obj = {}
    Object.defineProperty(obj, "secret", {
    value: "hidden",
    enumerable: false
    })
    console.log(Object.keys(obj)) // []
    console.log(obj.secret) // "hidden"
    

4. configurable(是否可重新定义或删除)

  • 默认 false,表示 无法删除该属性,也无法重新定义它
    let obj = {}
    Object.defineProperty(obj, "id", {
    value: 100,
    configurable: false
    })
    delete obj.id // 删除失败
    console.log(obj.id) // 仍然是 100
    

访问器描述符(get & set

除了 value,我们还可以使用 getter 和 setter 来定义动态计算属性

示例:定义一个计算属性

let user = {
  firstName: "John",
  lastName: "Doe"
}

Object.defineProperty(user, "fullName", {
  get() {
    return this.firstName + " " + this.lastName
  },
  set(value) {
    [this.firstName, this.lastName] = value.split(" ")
  }
})

console.log(user.fullName) // "John Doe"
user.fullName = "Alice Smith"
console.log(user.firstName) // "Alice"
console.log(user.lastName) // "Smith"
  • get():每次访问 fullName 时,都会执行 get 方法,动态计算值。
  • set(value):允许修改 fullName,并将输入拆分成 firstNamelastName

与普通属性赋值的区别

普通赋值(obj.prop = value 只能设置值,而 Object.defineProperty 可以:

  1. 定义不可修改的属性writable: false)。
  2. 隐藏属性enumerable: false)。
  3. 防止删除configurable: false)。
  4. 使用 getter/setter 处理动态计算

应用场景

1. 防止对象属性被修改

const settings = {}
Object.defineProperty(settings, "apiUrl", {
  value: "https://api.example.com",
  writable: false
})
settings.apiUrl = "https://new-api.com" // 失败
console.log(settings.apiUrl) // 仍然是 "https://api.example.com"

2. 隐藏属性

const user = { name: "Alice" }
Object.defineProperty(user, "password", {
  value: "secret123",
  enumerable: false
})
console.log(Object.keys(user)) // ["name"],password 不会出现
console.log(user.password) // 仍然可以访问 "secret123"

3. 创建计算属性

let cart = { price: 100, quantity: 2 }
Object.defineProperty(cart, "total", {
  get() {
    return this.price * this.quantity
  }
})
console.log(cart.total) // 200
cart.quantity = 3
console.log(cart.total) // 300(自动更新)

总结

特性 作用
value 定义属性的默认值
writable 是否可修改值(默认 false
enumerable 是否能被 for...inObject.keys() 访问(默认 false
configurable 是否能删除或重新定义(默认 false
get() 计算属性的 getter
set(value) 计算属性的 setter

什么时候用 Object.defineProperty

  • 需要不可修改的常量writable: false)。
  • 隐藏敏感信息enumerable: false)。
  • 计算属性(getter/setter)
  • 增强安全性,防止外部修改重要对象

如果你只是想简单地给对象添加属性,普通赋值 obj.key = value 就够了。但如果你需要更细粒度的控制,就可以用 Object.defineProperty

更新于 2025-04-02

查看javascript更多相关的文章或提一个关于javascript的问题,也可以与我们一起分享文章