深入浅出Object.defineProperty

576 阅读2分钟

对象的定义与赋值

经常使用的定义与赋值方法obj.prop = value或者obj["prop"] = value

let person = {}
person.name = "myhua"
person["gender"] = "female"
console.log(person.name) // myhua
console.log(person.gender) // female

Object.defineProperty()语法说明

Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性

Object.defineProperty(obj, prop, desc)
// obj 需要定义属性的当前对象
// prop 当前需要定义的属性名
// desc 属性描述符

属性描述符的默认属性

属性名 默认值 描述
value undefined 当前对象属性的值
get undefined 给属性提供getter方法,该方法返回值作为属性值。
set undefined 给属性提供setter方法,该方法将接受唯一参数,并将该参数的新值分配给该属性。
writable false 当前对象属性的值是否能够改变
enumerable false 当前对象属性是否会可以在for in 或者 Object.keys()中被枚举
configurable false configurable 特性表示对象的属性是否可以被删除,以及除 value 和 writable 特性外的其他特性是否可以被修改。

数据描述符(value,writable)

writabletrue

let person = {}
Object.defineProperty(person, "name", {
  value: "jack",
  writable: true
})
console.log(person) // {name: "jack"}
console.log(person.name) // jack
person.name = "myhua"
console.log(person) // {name: "myhua"}
console.log(person.name) // myhua

writablefalse

let person = {}
Object.defineProperty(person, "name", {
  value: "jack"
})
console.log(person) // {name: "jack"}
console.log(person.name) // jack
person.name = "myhua" // 此处不会抛出异常
console.log(person) // {name: "jack"}
console.log(person.name) // jack

存取描述符(set,get)

let person = {}
let temp = null
Object.defineProperty(person, 'name', {
  get: function () {
    return temp
  },
  set: function (val) {
    temp = val
  }
})
person.name = "myhua"
console.log(person) // {}
console.log(person.name) // myhua

数据描述符与存取描述符不能同时存在,否则会抛出一个异常

通用描述符(configurable,enumerable)

数据描述符和存取描述都具有configurable,enumerable描述符
当configurable为true时

// 第一种情况,删除
let person = {}
Object.defineProperty(person, 'name', {
  value: "jack",
  writable: true,
  configurable: true
})
console.log(person.name) // jack
delete person.name
console.log(person.name) // undefined

// 第二种情况,修改
let person = {}
Object.defineProperty(person, 'name', {
  value: "jack",
  writable: true,
  configurable: true
})
// 无异常
Object.defineProperty(person, 'name', {
  value: "myhua",
  writable: true,
  configurable: false
})

当configurable为false时

// 第一种情况,删除
let person = {}
Object.defineProperty(person, 'name', {
  value: "jack",
  writable: true
})
console.log(person.name) // jack
delete person.name // 此处不会抛出异常
console.log(person.name) // jack

// 第二种情况,修改
let person = {}
Object.defineProperty(person, 'name', {
  value: "jack",
  writable: true
})
// 抛出异常 Uncaught TypeError: Cannot redefine property: name at Function.defineProperty (<anonymous>)
Object.defineProperty(person, 'name', {
  value: "myhua",
  writable: true,
  configurable: true
})

enumerable测试

let person = {}
Object.defineProperty(person, "name", {
  value: "jack",
  enumerable: false
})
person.gender = "female"
Object.defineProperty(person, "age", {
  value: "jack",
  enumerable: true
})
console.log(Object.keys(person)) // ["gender", "age"]
for(let key in person) {
  console.log(key) //gender,age
}

常用的对象属性定义方法与Object.defineProperty的关系

person.gender = "female"

// 等同于

Object.defineProperty(person, "gender", {
  value: "female",
  writable: true,
  configurable: true,
  enumerable: true
})