物件屬性取值

本文探討物件屬性取值可能會遇到的兩件事與其解法

取不到值時的後續處理

物件屬性取值時,若取不到值而得到 undefined,要怎麼給定預設值?

情境如下,物件 people 使用 ES6 解構

const people = {
  name: 'Nina',
  age: '25',
  family: {
    father: 'David',
    mother: 'Jenny',
    brother: 'Nick',
    sister: 'Anna'
  },
};

const { family: { grandFather } } = people;

console.log(`grandFather: ${grandFather}`); // 取不到值,得到 undefined

其中 grandFather 被解構和宣告,但物件 people 沒有對應屬性,因此取不到值,得到 undefined。

解法 1:Lodash 的 _.get

使用 Lodash 的 _.get 取值,即可在第三個參數設定預設值,避免得到 undefined 的狀況。

const grandFather = _.get(people, 'family.grandFather', 'John');
console.log(`grandFather: ${grandFather}`); // "grandFather: John"

解法 2:Optional Chaining

關於檢視物件中是否存在某屬性,再依照存在與否回傳值或 undefined,可用 Optional Chaining,但目前只是實驗功能,需要搭配 babel 才能使用。

如下,dogName 照理說應該直接報錯「Uncaught TypeError: Cannot read property ‘name’ of undefined」,但得到 undefined;rabbitName 由於也是得到 undefined,因此可利用 || 來設定初始值,再得到 Nina。

const adventurer = {
  name: 'Alice',
  cat: {
    name: 'Dinah'
  }
};

const dogName = adventurer.dog?.name;
console.log(dogName); // undefined

const rabbitName = adventurer.rabbit?.name || 'Nina';
console.log(rabbitName); // Nina

ReferenceError vs undefined

ReferenceError 和 undefined 這兩者的差異

範例。

var a;

console.log(`a: ${a}`); // a: undefined
console.log(`b: ${b}`); // ReferenceError: b is not defined

比較常見的發生狀況是…「沒取到」與「以為取到」的 undefined 和 ReferenceError…滿多 腦殘的 人都會誤將存在的屬性當成有宣告的變數在用,出錯了還不知道發生事 (  ̄ 3  ̄)y▂ξ

const people = {
  name: 'Nina',
  age: '25',
  family: {
    father: 'David',
    mother: 'Jenny',
    brother: 'Nick',
    sister: 'Anna'
  },
};

const { family: { grandFather } } = people;

console.log(`grandFather: ${grandFather}`); // 取不到值,得到 undefined
console.log(`brother: ${brother}`); // ReferenceError: brother is not defined

其中

屬性的名稱用點 . 分隔,要怎麼取值

eat.snack 是一個屬性的名稱,但由於中間用點隔開,因此無法被正確解構。

const people = {
  name: 'Nina',
  age: '25',
  family: {
    father: 'David',
    mother: 'Jenny',
    brother: 'Nick',
    sister: 'Anna'
  },
  'eat.snack': 'cake',
};

const { eat.snack } = people; // Uncaught SyntaxError: Unexpected token '.'

解法 1:陣列

使用陣列且 key 放字串的方式處理。

people['eat.snack']; // 'cake'

解法 2:Lodash 的 _.get

使用 Lodash 的 _.get 取值。

如下,將 eat.snack 這個屬性名稱放入第二個 path 參數即可。

const people = {
  name: 'Nina',
  age: '25',
  family: {
    father: 'David',
    mother: 'Jenny',
    brother: 'Nick',
    sister: 'Anna',
  },
  'eat.snack': 'cake',
};

const eatSnack = _.get(people, 'eat.snack');

console.log(`eatSnack: ${eatSnack}`); // "eatSnack: cake"

_.get 對於屬性用點分隔的方式,僅可查找指定到的當層而已,若是下一層或多層就會找不到。

const people = {
  // 略
  eat: {
    'eat.snack': 'cake',
    eat: {
      snack: 'not this cake',
    },
  },
};

const eatSnack = _.get(people, 'eat.eat.snack'); // 找不到,以為路徑是 eat > eat > snack

console.log(`eatSnack: ${eatSnack}`); // "not this cake"

總結 _.get 比起 ES6 原生的解構來說,優點是


javascript object operator 運算子 ES6 ReferenceError undefined javascript