# 数据属性描述符

  • 数据数据描述符有如下四个特性:

  • [[Configurable]]:表示属性是否可以通过 delete 删除属性,是否可以修改它的特性,或者是否可以将它修改为存取属性描述符;

  • 当我们直接在一个对象上定义某个属性时,这个属性的 [[Configurable]] 为 true;

  • 当我们通过属性描述符定义一个属性时,这个属性的 [[Configurable]] 默认为 false;

  • [[Enumerable]]:表示属性是否可以通过 for-in 或者 Object.keys () 返回该属性;

    • 当我们直接在一个对象上定义某个属性时,这个属性的 [[Enumerable]] 为 true;
    • 当我们通过属性描述符定义一个属性时,这个属性的 [[Enumerable]] 默认为 false;
  • [[Writable]]:表示是否可以修改属性的值;

  • 当我们直接在一个对象上定义某个属性时,这个属性的 [[Writable]] 为 true;

  • 当我们通过属性描述符定义一个属性时,这个属性的 [[Writable]] 默认为 false;

  • [[value]]:属性的 value 值,读取属性时会返回该值,修改属性时,会对其进行修改;

    • 默认情况下这个值是 undefined;

测试代码

var neko = {
  friend: 'lain'
}
Object.defineProperty(neko, 'friend', {
  value: 'Saber',
  writable: false,
  configurable: false,
  enumerable: false,
})
new Promise((resolve, reject) => {
  setTimeout(() => {
  console.log('修改friend之前',neko);
  neko.friend = 'lain'
  console.log('修改friend之后',neko);
  resolve(neko)
  },1000)
})
.then(res => {
  setTimeout(() => {
    console.log('删除friend之前',res);
    delete neko.friend
    console.log('删除friend之后',res);
  } ,1000)
})
.then(() => {
  setTimeout(() => {
    for (var key in neko) {
      console.log(key) //friend 不可遍历所
    }
    console.log(Object.keys(neko))
  },1000)  
})

# 存取属性描述符

  • 数据数据描述符有如下四个特性:
  • [[Configurable]]:表示属性是否可以通过 delete 删除属性,是否可以修改它的特性,或者是否可以将它修改为存取属性描述符;
    • 和数据属性描述符是一致的;
    • 当我们直接在一个对象上定义某个属性时,这个属性的 [[Configurable]] 为 true;
    • 当我们通过属性描述符定义一个属性时,这个属性的 [[Configurable]] 默认为 false;
  • [[Enumerable]]:表示属性是否可以通过 for-in 或者 Object.keys () 返回该属性;
    • 和数据属性描述符是一致的;
    • 当我们直接在一个对象上定义某个属性时,这个属性的 [[Enumerable]] 为 true;
    • 当我们通过属性描述符定义一个属性时,这个属性的 [[Enumerable]] 默认为 false;
  • [[get]]:获取属性时会执行的函数。默认为 undefined
  • [[set]]:设置属性时会执行的函数。默认为 undefined

测试代码

const lain = {
  _friend: 'nekoaimer'
}
Object.defineProperty(lain, "friend", {
  configurable: true,
  enumerable: true,
  get: function() {
    bar()
    return this._friend
  },
  set: function(value) {
    foo()
    console.log('value:', value) // 设置的值
    this._friend = value
  }
})
console.log(lain.friend)
lain.friend = 'Saber'
console.log(lain.friend)
function foo() {
  console.log('设置了friend的值')
}
function bar() {
  console.log("获取了一次friend的值",)
}

# 同时定义多个属性

  • Object.defineProperties () 方法直接在一个对象上定义 多个 新的属性或修改现有属性,并且返回该对象。
const lain = {
  _age: 16,
  _friend: 'nekoaimer'
}
Object.defineProperties(lain, {
  age: {
    configurable: true,
    enumerable: true,
    value: 16,
    writable: true
  },
  friend: {
    configurable: false,
    enumerable: false,
    get() { 
      console.log('get', this._friend);
      return this._friend
    },
    set(value) {
      console.log('set', value) 
      this._friend = value
    }
  }
})
lain.age = 18
console.log('lain._age:', lain._age);
lain.friend = 'Saber'
console.log('lain.friend:' ,lain.friend);
console.log(lain);

默认为 true 的写法

const lain = {
  _age: 16,
  _friend: 'nekoaimer',
  set age(value) {
    this._age = value
  },
  get age() {
    return this._age 
  }
}
Object.defineProperties(lain, {
  // age: {
  //   configurable: true,
  //   enumerable: true,
  //   value: 16,
  //   writable: true
  // },
  friend: {
    configurable: false,
    enumerable: false,
    get() { 
      console.log('get', this._friend);
      return this._friend
    },
    set(value) {
      console.log('set', value) 
      this._friend = value
    }
  }
})
lain.age = 18
console.log('lain._age:', lain._age);
lain.friend = 'Saber'
console.log('lain.friend:' ,lain.friend);
console.log(lain);

# 获取属性描述符

const lain = {
  _age: 16,
  _friend: 'nekoaimer',
  set age(value) {
    this._age = value
  },
  get age() {
    return this._age 
  }
}
Object.defineProperties(lain, {
  friend: {
    configurable: false,
    enumerable: false,
    get() { 
      console.log('get', this._friend);
      return this._friend
    },
    set(value) {
      console.log('set', value) 
      this._friend = value
    }
  }
})
// 获取某一个特性属性的属性描述符
console.log('age', Object.getOwnPropertyDescriptor(lain, 'age'))
console.log('friend', Object.getOwnPropertyDescriptor(lain, 'friend'))
// 获取对象的所有属性描述符
console.log('lain', Object.getOwnPropertyDescriptors(lain))

# Object 方法对对象限制

# 禁止对象继续添加新的属性

const lain = {
  age: 16,
  friend: 'Saber',
}
Object.preventExtensions(lain)
lain.height = 1.65
lain.sex = "girl"
console.log(lain)  // {age: 16, friend: 'Saber'}

# 禁止对象配置 / 删除里面的属性

const lain = {
  age: 16,
  friend: 'Saber',
}
Object.seal(lain)
delete lain.friend
console.log(lain.friend) // Saber

# 冻结属性:让属性不可以修改 (writable: false)

const lain = {
  age: 16,
  friend: 'Saber',
}
// 只冻结一级属性
Object.freeze(lain)
lain.friend = "Lain"
console.log(lain.friend) // Saber