js的对象属性

390 阅读3分钟

对象定义

ECMAScript把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数。严格来说,这就是相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。其中值可以是数据或者函数。 每一个对象都是基于一个引用类型创建的,这个引用类型可以是原生类型,也可以是开发人员定义的类型。

属性类型

ECMAScript 中有两种属性:数据属性和访问器属性

数据属性

数据属性有4个描述行为的特性:

  • [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,默认值为true
  • [[Enumerable]]:表示能否通过for-in循环返回属性,默认值为true
  • [[Writable]]:表示能否修改属性的值,默认值为true
  • [[Value]]:表示这个属性的数据值,默认为undefined

修改数据属性默认值

使用object.defineProperty()方法(注意:使用object.definedProperty方法创建一个新的属性时,如果不指定,configurable、enumerable和writable这些特性都默认为false

  • 例子
const person = {name: 'Li'}
Object.defineProperty(person, 'name', {
 writable: false,
 value: 'Joy'
})
// {name: "Joy"}
console.log(person)
person.name = 'test'
// 因为设置了writable: false所以name的值不能被修改
// {name: "Joy"}
console.log(person)
  • 修改configurable属性 设置configurable为false,表示不能从对象中删除属性,而且,一旦configurable设置为false就不能把它再重新设置回true了,再调用object.definedProperty方法修改writeable之外的特性都会报错。
let person = {name: 'Li'}
Object.defineProperty(person, 'name', {
 configurable: false,
 writable: false,
 value: 'Joy'
})

console.log(person)

// 抛出错误
Object.defineProperty(person, 'name', {
 configurable: true,
 value: 'Li'
})
console.log(person)

访问器属性

访问器属性有如下4个特征:

  • [[configurable]]:表示能否通过delete删除属性从而重新定义属性,默认为true
  • [[enumerable]]:表示能否通过for-in循环返回属性,默认为true
  • [[get]]:在读取属性时调用的函数,默认值为undefined
  • [[set]]:在写入属性值时调用的函数,默认值为undedined

使用object.defineProperty方法来定义访问器属性

以下代码创建了一个book对象,并定义了两个默认属性: _year和edition,_下划线表示_year这个属性只能通过对象方法访问的属性。(只是一种记号)

let book = {
  _year: 2004,
  edition: 1
}

Object.defineProperty(book, 'year', {
  get: function() { return this._year },
  set: function(newValue) {
    if(newValue > 2004) {
      this._year = newValue
      this.edition += newValue - 2004
    }
  }
})

book.year = 2005
// {_year: 2005, edition: 2}
console.log(book)

使用Object.defineProperties定义多个属性

let book = {};
Object.defineProperties(book, {
  _year: {
    writable: true,
    value: 2021
  },
  edition: {
     writable: true,
     value: 1
  },
  year: {
     get: function() { return this._year },
     set: function(newValue) {
       if(newValue > 2004) {
         this._year = newValue
         this.edition += newValue - 2004
       }
     }
   }
})
book.year = 2005
console.log(book)

注意

  • 只指定getter意味着属性是不能写的,非严格模式尝试写入属性会被忽略,严格模式会抛出错误

  • 只指定setter意味着不能读,非严格模式会返回undefined,严格模式会抛出错误

读取属性特征

Object.getOwnPropertyDescriptor方法,可以取得给定属性的描述符。

let book = {};
Object.defineProperties(book, {
  _year: {
    writable: true,
    value: 2021
  },
  edition: {
     writable: true,
     value: 1
  },
  year: {
     get: function() { return this._year },
     set: function(newValue) {
       if(newValue > 2004) {
         this._year = newValue
         this.edition += newValue - 2004
       }
     }
   }
})
book.year = 2005
// {value: 2005, writable: true, enumerable: false, configurable: false}
console.log(Object.getOwnPropertyDescriptor(book, '_year'))