物件的 rest 和 spread 屬性

發佈於 · 標籤為 ECMAScript ES2018

在討論物件的 rest 和 spread 屬性之前,讓我們來趟時光之旅,回顧一下一個非常類似的功能。

ES2015 陣列的 rest 和 spread 元素 #

ES2015 這個好夥伴引入了rest 元素,用於陣列解構賦值,以及spread 元素,用於陣列文字。

// Rest elements for array destructuring assignment:
const primes = [2, 3, 5, 7, 11];
const [first, second, ...rest] = primes;
console.log(first); // 2
console.log(second); // 3
console.log(rest); // [5, 7, 11]

// Spread elements for array literals:
const primesCopy = [first, second, ...rest];
console.log(primesCopy); // [2, 3, 5, 7, 11]
  • Chrome: 自版本 47 起支援
  • Firefox: 自版本 16 起支援
  • Safari: 自版本 8 起支援
  • Node.js: 自版本 6 起支援
  • Babel: 支援

ES2018: 物件的 rest 和 spread 屬性 🆕 #

那麼,有什麼新功能呢?嗯,這項提案也為物件文字啟用了 rest 和 spread 屬性。

// Rest properties for object destructuring assignment:
const person = {
firstName: 'Sebastian',
lastName: 'Markbåge',
country: 'USA',
state: 'CA',
};
const { firstName, lastName, ...rest } = person;
console.log(firstName); // Sebastian
console.log(lastName); // Markbåge
console.log(rest); // { country: 'USA', state: 'CA' }

// Spread properties for object literals:
const personCopy = { firstName, lastName, ...rest };
console.log(personCopy);
// { firstName: 'Sebastian', lastName: 'Markbåge', country: 'USA', state: 'CA' }

在許多情況下,spread 屬性提供了比 Object.assign() 更簡潔的替代方案

// Shallow-clone an object:
const data = { x: 42, y: 27, label: 'Treasure' };
// The old way:
const clone1 = Object.assign({}, data);
// The new way:
const clone2 = { ...data };
// Either results in:
// { x: 42, y: 27, label: 'Treasure' }

// Merge two objects:
const defaultSettings = { logWarnings: false, logErrors: false };
const userSettings = { logErrors: true };
// The old way:
const settings1 = Object.assign({}, defaultSettings, userSettings);
// The new way:
const settings2 = { ...defaultSettings, ...userSettings };
// Either results in:
// { logWarnings: false, logErrors: true }

不過,spread 處理 setter 的方式有一些細微的差異

  1. Object.assign() 會觸發 setter,但 spread 卻不會。
  2. 你可以透過繼承的唯讀屬性來阻止 Object.assign() 建立自己的屬性,但無法阻止 spread 運算子。

Axel Rauschmayer 的文章更詳細地說明了這些陷阱。

  • Chrome: 自版本 60 起支援
  • Firefox: 自版本 55 起支援
  • Safari: 自版本 11.1 起支援
  • Node.js: 自版本 8.6 起支援
  • Babel: 支援