欢迎关注前端小讴的github,阅读更多原创技术文章

理解对象

  • 面向对象的语言标志:的概念
  • ECMAScript 中没有类的概念
  • ECMAScript 定义对象:无序属性的集合(一组没有特定顺序的值),其属性可以包含基本值对象函数,整个对象可以想象成一个散列表

相关代码 →

  • 创建一个 Object 实例,然后为它添加属性和方法
var person = new Object()
person.name = 'Nicholas'
person.age = 29
person.job = 'Software Engineer'
person.sayName = function () {
  console.log(this.name)
}
  • 对象字面量创建对象
var person = {
  name: 'Nicholas',
  age: 29,
  job: 'Software Engineer',
  sayName: function () {
    console.log(this.name)
  },
}

属性类型

数据属性含义默认值
[[Configurable]]能否通过 delete 删除属性 / 能否修改属性特性 / 能否把属性改为访问器属性直接在对象上定义时:true / 使用 Object.defineProperty()等方法定义时:false
[[Enumerable]]能否通过 for-in 循环返回属性直接在对象上定义时:true / 使用 Object.defineProperty()等方法定义时:false
[[Writable]]能否修改属性的值直接在对象上定义时:true / 使用 Object.defineProperty()等方法定义时:false
[[Value]]属性的数据值undefined
var person = {
  name: 'Nicholas',
}
  • 数据属性包含一个数据值的位置,用 Object.defineProperty() 修改默认属性
  • 方法接收 3 个参数:属性所在的对象、属性名、描述符对象(描述符对象属性必须是:configurable / enumerable / writable / value,一个或多个)
  • 严格模式下,操作会报错
Object.defineProperty(person, 'name', {
  writable: false, // 不可修改
  configurable: false, // 不可配置
  value: 'Nicholas',
})
console.log(person.name)
person.name = 'Greg'
console.log(person.name) // 无法重写
delete person.name
console.log(person.name) // 无法删除
  • 一旦属性定义为不可配置,不能再变回可配置,再次调用 Object.defineProperty() 方法修改除 writable 以外的特性都会报错
Object.defineProperty(person, 'name', {
  configurable: true, // 试图:不可配置 -> 可配置,由于已经改为不可配置,因此会报错
  value: 'Simon',
})
  • 可多次调用 Object.defineProperty() 修改同一属性,一但把 configurable 设置为 false 之后就会有限制了
访问器属性含义默认值
[[Configurable]]能否通过 delete 删除属性 / 能否修改属性特性 / 能否把属性改为数据属性直接在对象上定义时:true / 使用 Object.defineProperty()等方法定义时:false
[[Enumerable]]能否通过 for-in 循环返回属性直接在对象上定义时:true / 使用 Object.defineProperty()等方法定义时:false
[[Get]]读取属性时调用的函数undefined
[[Set]]写入属性时调用的函数undefined
var book = {
  _year: 2004,
  edition: 1,
}
  • 访问器属性不包含数据值,用 Object.defineProperty() 定义属性
  • 方法接收 3 个参数:属性所在的对象、属性名、描述符对象(和数据属性用法一样)
  • 只指定 getter -> 属性不能写;只指定 setter -> 属性不能读
  • 严格模式下,只指定 getter 或 setter 均会报错
Object.defineProperty(book, 'year', {
  get: function () {
    return this._year
  },
  set: function (newValue) {
    if (newValue > 2004) {
      this._year = newValue
      this.edition += newValue - 2004
    }
  },
})

book.year = 2007
console.log(book.edition)
  • IE8 或更早,定义访问器属性的方法(遗留的方法,可在浏览器测试,vscode 会报错)
book.__defineGetter__('year', function () {
  return this._year
})
book.__defineSetter__('year', function (newValue) {
  if (newValue > 2004) {
    this._year = newValue
    this.edition += newValue - 2004
  }
})
book.year = 2008
console.log(book.edition)
  • 调用 Object.defineProperty()、Object.defineProperties()方法时,如果不指定,即非“直接在对象上定义属性”时,那么 configurable、enumerable、writable 均为 false
var book4 = {
  year: 2004,
}
var descriptorBook4 = Object.getOwnPropertyDescriptor(book4, 'year')
console.log(
  'book4',
  descriptorBook4.configurable, // true
  descriptorBook4.enumerable, // true
  descriptorBook4.writable, // true
  typeof descriptorBook4.set, // undefined
  typeof descriptorBook4.get // undefined
)
var book5 = {}
Object.defineProperty(book5, 'year', {
  value: 2004,
})
var descriptorBook5 = Object.getOwnPropertyDescriptor(book5, 'year')
console.log(
  'book4',
  descriptorBook5.configurable, // false
  descriptorBook5.enumerable, // false
  descriptorBook5.writable, // false
  typeof descriptorBook4.set, // undefined
  typeof descriptorBook4.get // undefined
)

定义多个属性

  • Object.defineProperties() 同时定义多个属性
  • 同时定于多个属性,与分别修改和定义对象的属性的唯一却别,是这些属性都是在同一时间创建的
var book2 = {}
Object.defineProperties(book2, {
  _year: {
    writable: true,
    value: 2004,
  },
  edition: {
    writable: true,
    value: 1,
  },
  year: {
    get: function () {
      return this._year
    },
    set: function (newValue) {
      if (newValue > 2004) {
        this._year = newValue
        this.edition += newValue - 2004
      }
    },
  },
})
book2.year = 2008
console.log(book2.edition) // 5

读取属性的特性

  • Object.getOwnPropertyDescriptor() 取得给定属性的描述符
var book3 = {}
Object.defineProperties(book3, {
  _year: {
    value: 2004,
  },
  edition: {
    value: 1,
  },
  year: {
    get: function () {
      return this._year
    },
    set: function (newValue) {
      if (newValue > 2004) {
        this._year = newValue
        this.edition += newValue - 2004
      }
    },
  },
})
var descriptor = Object.getOwnPropertyDescriptor(book3, '_year')
console.log(descriptor)
console.log(descriptor.value) // 2004
console.log(descriptor.configurable) // false,非直接在对象上定义属性,默认值为false
console.log(typeof descriptor.get) // undefined,数据属性不含get函数

var descriptor2 = Object.getOwnPropertyDescriptor(book3, 'year')
console.log(descriptor2)
console.log(descriptor2.value) // undefined,访问器属性不含value
console.log(descriptor2.configurable) // false,非直接在对象上定义属性,默认值为false
console.log(typeof descriptor2.get) // 'function'

总结 & 问点

  • 面向对象的语言的标志是什么?JS 的对象是什么?
  • 创建 JS 对象都有哪些方法?
  • JS 对象有哪些属性类型?其分别有哪些特性?
  • 用哪些方法如何修改或定义 JS 对象的属性?
  • 用哪个方法如何读取对象属性的特性?

小讴
217 声望16 粉丝