《javascript高級程序設計》學習筆記 | 6.1.理解對象

歡迎關注前端小謳的github,閱讀更多原創技術文章

理解對象

  • 面向對象的語言標誌:的概念
  • ECMAScript 中沒有類的概念
  • ECMAScript 定義對象:無序屬性的集合(一組沒有特定順序的值),其屬性能夠包含基本值對象函數,整個對象能夠想象成一個散列表

相關代碼 →javascript

  • 建立一個 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
[[Enumerable]] 可否經過 for-in 循環返回屬性 true
[[Writable]] 可否修改屬性的值 true
[[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
[[Enumerable]] 可否經過 for-in 循環返回屬性 true
[[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 對象的屬性?
  • 用哪一個方法如何讀取對象屬性的特性?
相關文章
相關標籤/搜索