訪問物件的屬性,你知道有哪些方法?

語言: CN / TW / HK

相信物件對於每個使用JavaScript的人來說都不陌生。訪問物件的屬性幾乎日常開發每天都在用。下面我們一起探索下有哪些方式可以實現屬性的訪問。

訪問物件屬性介紹

物件是JavaScript的一種常見的資料型別。它允許我們以鍵值對的形式儲存資料。這一系列的鍵成為物件的屬性。

常見的訪問物件的屬性的方式有三種,包括點號、方括號和物件分解。點號也經常被叫做點號屬性訪問器。而方括號表示法也被稱為方括號屬性訪問器。

這三種訪問方式都是在你知道屬性名的情況下,否則於事無補。你只能通過迴圈遍歷獲取所有的屬性,其中包括你想要獲取的那個屬性。下面來分別看下三種訪問方式。

點號

點號訪問器是訪問屬性裡用的最多的一種方式。或許是最簡單的一種形式。語法就是你先指定一些物件,然後根據你所知道的屬性名,在物件和屬性名之間用點號連線。

使用同樣的方式你也可以訪問物件裡更深層次的屬性。通過層層巢狀的方式將它們連線起來。例如 obj.shallowProp.deeperProp.DeepestProp

// Create an object using object literal:
const myObj = {
  name: 'Anthony Edward Stark',
  alias: 'Iron Man',
  gender: 'male',
  education: 'MIT',
  affiliation: {
    current: 'Avengers'
  },
  creators: ['Stan Lee', 'Larry Lieber', 'Don Heck', 'Jack Kirby'],
  status: {
    alignment: 'good'
  }
}

// Accessing object properties with dot notation:
// First: name of the object.
// Second: name of the property to access.
// Third: dot character between the object and property.
console.log(myObj.name)
// Output:
// 'Anthony Edward Stark'

// Accessing deeper object properties:
// Access the "current" property that exists
// in nested object assigned to "affiliation" property
console.log(myObj.affiliation.current)
// Output:
// 'Avengers'

在JavaScript中,有規則說明什麼是有效識別符號和無效識別符號。有效識別符號包含Unicode字母、$、_和數字0-9。但是不能以數字開頭。當我們在宣告變數的時候要注意這些規則。

在使用點訪問器也要注意屬性名的有效性。點訪問器只在有效的識別符號的情況下訪問才有結果。如果該屬性名以數字開頭或者只包含數字,再或者包含 - 符號,就不能使用點訪問器。

這個時候我們就得使用方括號訪問器了。

// Create an object:
myObj = {
  1: 'First property',
  'first-name': 'Bruce',
}

// Try to use dot notation
// to access properties on "myObj".
console.log(myObj.1)
// Output:
// SyntaxError: Unexpected token

console.log(myObj.first-name)
// Output:
// NaN

// Try to use bracket notation
// to access properties on "myObj".
console.log(myObj['1'])
// Output:
// 'First property'

console.log(myObj[1])
// Output:
// 'First property'

console.log(myObj['first-name'])
// Output:
// 'Bruce'

方括號

第二種訪問物件屬性的方式就是方括號表示法。顧名思義就是通過方括號去訪問,和點號有點類似。但是又有很大的區別。

首先我們給屬性名加上引號,單引號或者雙引號都可以。然後給它們整體用方括號包起來放在物件的後面。

方括號訪問器也支援一級以上的屬性訪問。和點號類似。如果遇到屬性值為陣列的情況,則通過方括號加索引值得方式來獲取該變數。

// Create an object:
const myObj = {
  name: 'Bruce Thomas Wayne',
  alias: 'Batman',
  affiliation: ['Batman Family', 'Justice League', 'Outsiders', 'Guild of Detection'],
  status: {
    alignment: 'good',
    occupation: 'businessman'
  }
}

// Accessing object properties with bracket notation:
// First: name of the object.
// Second: name of the property to access.
// Note: property name must be wrapped with quotes
// and then with square brackets.
console.log(myObj['name'])
// Output:
// 'Bruce Thomas Wayne'

// Accessing deeper object properties:
// Access the "alignment" property that exists
// in nested object assigned to "status" property
console.log(myObj['status']['alignment'])
// Output:
// 'good'

// Accessing array items in objects:
// Access the second item inside the array
// assigned to "affiliation" property.
console.log(myObj['affiliation'][1])
// Output:
// 'Justice League'

有趣的一點是方括號支援通過計算的屬性名進行訪問。簡而言之就是你一開始可能並不知道該屬性名,但是之後這個屬性名被存在某一個變數中,你可以引用此變數來訪問與變數值匹配的屬性。

注意區別在於,變數名放在方括號裡是不需要加引號的。

// Create an object:
const myObj = {
  name: 'James Howlett',
  alias: 'Wolverine',
  status: {
    alignment: 'good'
  }
}

// Assign a property you want to access to a variable:
const myProp = 'alias'

// Use the variable to access specific property ("alias"):
// Referencing "myProp" will return value "alias",
// which will be used to access the same property ("alias").
// I.e.: myObj[myProp] => myObj['alias']
console.log(myObj[myProp])
// Output:
// 'Wolverine'

物件分解法

最後一種訪問物件屬性的方式就是物件分解法。可能很少有人用到。作為ES6規範的一部分,解構最近被加到JavaScript中來。由於它的簡單易用,受到廣大開發者的喜愛。

經常在宣告變數的時候用到。在賦值運算的左邊使用大括號包起屬性的名稱,右邊即為物件。通過這種方式將指定的屬性的值來給變數賦值。

// Create an object:
const myObj = {
  name: 'Unknown',
  alias: 'The Joker',
  affiliation: ['Black Glove', 'Injustice Gang', 'Injustice League', 'Joker League of Anarchy', 'Justice League of Arkham'],
  status: {
    alignment: 'bad',
    occupation: 'criminal'
  }
}

// Extract the value of "alias" property:
const { alias } = myObj

// Log the value of new "alias" variable:
console.log(alias)
// Output:
// 'The Joker'

還可以同時給多個屬性解構,屬性名稱之間通過逗號隔開。

// Create an object:
const myObj = {
  name: 'Dr. Reed Richards',
  alias: 'Mister Fantastic',
  affiliation: 'Fantastic Four',
  status: {
    alignment: 'good'
  }
}


// Use object destructuring to assign multiple variables:
// Desctructure "name", "alias", "affiliation" and "status".
const { name, alias, affiliation, status } = myObj

// Log the values of new variables:
console.log(name)
// Output:
// 'Dr. Reed Richards'

console.log(alias)
// Output:
// 'Mister Fantastic'

console.log(affiliation)
// Output:
// 'Fantastic Four'

console.log(status)
// Output:
// { alignment: 'good' }

使用解構的方式為變數賦值變得如此簡單。但是如果你想給一個變數名不屬性名相同的變數賦值,怎麼辦?也是可以的,物件解構允許你給變數指定別名。這樣你就可以通過別名引用這個變數。

使用方式就是在左側的屬性名的後面通過 : 隔開。

// Create an object:
const myObj = {
  name: 'Bruce Banner',
  alias: 'Hulk',
  affiliation: ['S.H.I.E.L.D.'],
  status: {
    alignment: 'good'
  }
}

// Extract the value of "name" property
// and assign it to variable called "realName" (new alias).
const { name: realName } = myObj

// Use new alias "realName" to get the value
console.log(realName)
// Output:
// 'Bruce Banner'

如果你想從物件解構的屬性中同時改變多個變數名,方法類似。只要在每個屬性名的後面增加新的變數名,然後用 : 隔開即可。

// Create an object:
const myObj = {
  name: 'Oliver Jonas Queen',
  alias: 'Green Arrow',
  affiliation: ['Justice League', 'Justice Society International'],
  status: {
    alignment: 'good'
  }
}

// Change multiple variable names:
// Change variable for "name" to "realName".
// Change variable for "alias" to "heroName".
// Change variable for "affiliation" to "connection".
const { name: realName, alias: heroName, affiliation: connection } = myObj

// Log all values using new variable names:
console.log(realName)
// Output:
// 'Oliver Jonas Queen'

console.log(heroName)
// Output:
// 'Green Arrow'

console.log(connection)
// Output:
// [ 'Justice League', 'Justice Society International' ]

物件解構使用起來很爽吧,但是如果你訪問的屬性不存在會怎麼樣?有一種方式你可以做的是提供一個預設值。在屬性名不存在的時候,獲取的就是預設值。

我們將預設值通過 = 加到屬性名的後面,如果這個時候又為屬性名增加別名,那麼就加在別名的後面。

// Create an object:
const myObj = {
  name: 'Richard John Grayson',
  alias: 'Nightwing',
  status: {
    alignment: 'good'
  }
}

// Deconstruct the "name" property
// and add default value in case it doesn't exist.
const { name = 'Anonymous' } = myObj

// Log the value of name
console.log(name)
// Output:
// 'Richard John Grayson'

// Deconstruct the "name" property
// and "affiliation" property,
// change it to "connections" and add default value
// in case "affiliation" property doesn't exist.
const { name, affiliation: connections = 'No connections' } = myObj

// Log the value of new variable "connections":
console.log(connections)
// Output:
// 'No connections'

解構的時候遇到計算屬性怎麼辦?

和方括號訪問器類似,物件解構也支援屬性是一個變數的情況。除了使用方括號將屬性名包起來以外,值得一提的是,這個時候你必須要為它指定一個別名,否則會出現語法錯誤。

// Create an object:
const myObj = {
  name: 'Max Eisenhardt',
  alias: 'Magneto',
  status: {
    alignment: 'bad'
  },
  creators: ['Stan Lee', 'Jack Kirby']
}

// Assign a property you want to access to a variable:
const myProp = 'name'

// Use the variable to access specific property ("name")
// and also create alias for it:
// Referencing "myProp" will now return value "name",
// which will be used to access the "name" property.
const { [myProp]: name } = myObj

// Log the value of new variable "name":
console.log(name)
// Output:
// 'Wolverine'

// Use computed property name with default value:
const myProp = 'powers'

// Use the variable to access specific property ("powers")
// and create alias "abilities" for it.
// If the property doesn't exist, use 'Unknown'
// as the default value for the new variable.
const { [myProp]: abilities = 'Unknown' } = myObj

// Log the value of new variable "abilities":
console.log(abilities)
// Output:
// 'Unknown'

結論:以上三種訪問物件屬性的方式:點號和方括號和物件分解的方式。具體採用哪種,我們平時使用的時候根據具體情況而定,並沒有什麼好壞之分。尤其要注意每種使用方式的邊緣情況,以上都有說到。