JS 總結之物件

Karon_發表於2019-03-03

我們都知道,物件一般是類的例項,如 Java,Python 等這類面嚮物件語言,而 JavaScript 中沒有類,因此 JavaScript 中的物件不是類的例項,而是基於原型的物件。

JavaScript 中的物件 Object 是 7 種內建型別(number, string, null, undefined, boolean, object, symbol)之一,是由 key 和 value 組成,value 可以是任意資料型別。

? 建立

JavaScript 可以用 宣告形式構造形式 的方式建立物件

? 宣告形式

let obj = {
  name: `Jon`,
  age: 18,
  say: () => {
    console.log(`hello`)
  }
}
複製程式碼

這種方式建立的物件需要注意點是,按照命名規範命名的 key 加不加引號都可以,不符合命名規範的 key 要加引號,如:

let obj = {
  `first_name`: `Jon`,
}
複製程式碼

? 構造形式

let obj = new Object()
obj.name = `Jon`
obj.age = 18
obj.say = () => {
  console.log(`hello`)
}
複製程式碼

給構造器生成的物件新增屬性需要一個一個新增

⛏ 訪問

訪問一個物件的屬性值可以通過 . 操作符[] 操作符 進行訪問,舉個粟子:

. 操作符:要求屬性名滿足識別符號的命名規範

[] 操作符:可以接受任意 UTF-8/Unicode 字串作為屬性名

let obj = {
  `first_name`: `Jon`,
  age: 18,
  say: () => {
    console.log(`hello`)
  }
}

obj.age // 通過 .運算子 訪問,18
obj[`age`] // 通過 []操作符  訪問,18
obj[`first_name`] // 通過 []操作符 訪問,Jon
複製程式碼

? get/set

? 使用 get

let person = {
  _age: 18,
  get age () {
    return this._age
  }
}

person.age // Jon`s age: 18
複製程式碼

⛵️ 使用 set

let play = {
  game: [],
  set current (name) {
    this.game.push(name)
  }
}

play.current = `dota2`
play.game // [`dota2`]
複製程式碼

涉及 getter 和 setter 的 Object.create()、object.defineProperty()、object.defineProperties() 後待補充

? 物件的擴充套件(ES6 / ES7)

? 屬性簡寫

let name = `Jon`
let person = {name}
// 等同於
let person = {name: name}
複製程式碼

? 物件函式簡寫

let person = {
  say () {
    console.log(`hello`)
  }
}
// 等同於
let person = {
  say: function () {
    console.log(`hello`)
  }
}
複製程式碼

? 屬性表示式

屬性,方法名,getter 和 setter 都支援

let firstName = `first name`
let age = `age`
let current = `current`
let person = {
  [firstName] : `Jon`,
  get [age] () {
    return 18
  },
  set [current] (name) {
    this[firstName] = name
  }
}
person[`first name`] // `Jon`
person.age // 18
person.current = `karon`
person[`first name`] // `karon`
複製程式碼

注意:屬性表示式和簡寫不能同時使用,比如:

let firstName = `first name`
// 報錯
let person = {
  [firstName]
}
複製程式碼

? 屬性的遍歷

ES6 一共有 5 種方法可以遍歷物件的屬性。

  1. for…in 迴圈遍歷物件自身的和繼承的可列舉屬性(不含 Symbol 屬性)。

  2. Object.keys(obj) 返回一個陣列,包括物件自身的(不含繼承的)所有可列舉屬性(不含 Symbol 屬性)的鍵名。

  3. Object.getOwnPropertyNames(obj) 返回一個陣列,包含物件自身的所有屬性(不含 Symbol 屬性,但是包括不可列舉屬性)的鍵名。

  4. Object.getOwnPropertySymbols(obj) 返回一個陣列,包含物件自身的所有 Symbol 屬性的鍵名。

  5. Reflect.ownKeys(obj) 返回一個陣列,包含物件自身的所有鍵名,不管鍵名是 Symbol 或字串,也不管是否可列舉。

以上的 5 種方法遍歷物件的鍵名,都遵守同樣的屬性遍歷的次序規則。

首先遍歷所有數值鍵,按照數值升序排列。
其次遍歷所有字串鍵,按照加入時間升序排列。
最後遍歷所有 Symbol 鍵,按照加入時間升序排列。

? 物件解構、擴充套件運算子

let person = {
  name: `Jon`,
  age: 18,
  say () {
    console.log(`hello`)
  }
}

let {name, age, say} = person
複製程式碼

要求等號右邊必須是一個物件,否則會報錯,如:

let {a} = undefined // 報錯
let {a} = null // 報錯
複製程式碼

並沒有拷貝到原型物件上的屬性

let name = {name: `Jon`}
let person = {age: 18}
person.__proto__ = name
let {...a} = person
a.name // undefined
複製程式碼

如果屬性物件,只是拷貝引用

let person = { habit: {name: `play game` }}
let {...a} = person
person.habit.name = `study`
a.habit.name // study
複製程式碼

展開

let obj = {
  name: `Jon`,
  age: 18
}

let person = {...obj}
person // { name: `Jon`, age: 18 }
複製程式碼

利用展開可以用來合併物件

let gift = { skill: `faster` }
let person = {
  name: `barry`
}
let flash = {...person, ...gift}
flash // {name: `barry`, skill: `faster`}
複製程式碼

? 新增的常用方法

【es6】Object.is(..)

比較兩個值是否相同,與 === 嚴格比較的區別在 +0 與-0,NaN 與 NaN

+0 === -0 // true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
複製程式碼

【es6】Object.assign(..)

物件合併,將後面的物件的屬性複製給第一個引數,也就是目標物件,需注意:可複製的屬性為自身屬性和可列舉的屬性,繼承而來的屬性無法被複制,如果是相同屬性,後面的會覆蓋前面的,舉個例子:

let person = { name: `barry`, skill: `run` }
let superSkill = {skill: `flash`}
Object.assign({}, person, superSkill) // {name: `barry`, skill: `flash`}
複製程式碼

也可以用來處理陣列,如下,b 把 a 引索為 0 和 1 的覆蓋了

let a = [1, 2, 3]
let b = [4, 5]
Object.assign([], a, b) // [4, 5, 3]
複製程式碼

【es6】Object.keys(..)

遍歷自身屬性,不含繼承屬性和 Symbol 屬性

let person = { name: `barry`, skill: `run`, [Symbol(`skill`)]: `run flash`}
Object.keys(person) // [`name`, `skill`]
複製程式碼

【es6】Object.getOwnPropertySymbols(..)

let person = {
  [Symbol(`skill`)]: `run flash`
}

Object.getOwnPropertySymbols(person) // [Symbol(skill)]
複製程式碼

【es7】Object.values(..)

遍歷自身屬性,不含繼承屬性和 Symbol 屬性

let person = { name: `barry`, skill: `run`, [Symbol(`skill`)]: `run flash`}
Object.values(person) // [`barry`, `run`]
複製程式碼

【es7】Object.entries(..)

遍歷自身屬性,不含繼承屬性和 Symbol 屬性

let person = { name: `barry`, skill: `run`, [Symbol(`skill`)]: `run flash`}
Object.entries(person) // [[`name`, `barry`], [`skill`, `run`]]
複製程式碼

將物件轉為 Map 物件:

let person = { name: `barry`, skill: `run`, [Symbol(`skill`)]: `run flash`}
let personArr = Object.entries(person) // [[`name`, `barry`], [`skill`, `run`]]
let personMap = new Map(personArr) // Map { name: `barry`, skill: `run` }
複製程式碼

【es7】Object.fromEntries(..)

為 Object.entries()的逆操作,用於將一個鍵值對陣列轉為物件。

let person = [[`name`, `barry`], [`skill`, `run`]]
Object.fromEntries(person) // { name: `barry`, skill: `run` }
複製程式碼

【es7】Object.getOwnPropertyDescriptors(..)
獲取物件所有自身的屬性描述符

let barry = { name: `barry`, skill: `run` }
Object.getOwnPropertyDescriptors(barry)
/* {
  name: {
    value: "barry",
    configurable: true,
    enumerable: true,
    writable: true
  },
  skill: {
    value: "run",
    configurable: true,
    enumerable: true,
    writable: true
  }
} */
複製程式碼

對應的有:【ES5】的 Object.getOwnPropertyDescriptor(..)

? 參考

相關文章