Khám phá Destructuring, Rest Parameters, và Spread Syntax trong JavaScript

1. Giới thiệu

Nhiều tính năng mới để làm việc với mảng và đối tượng đã được thêm vào JavaScript kể từ Phiên bản 2015 của ECMAScript. Một vài trong số những điều đáng chú ý mà bạn sẽ học trong bài viết này là destructuring, rest parameters, và spread synt. Các tính năng này cung cấp nhiều cách truy cập trực tiếp hơn vào các phẩn tử của một mảng hoặc một đối tượng và có thể làm việc với các cấu trúc dữ liệu này nhanh hơn và ngắn gọn hơn.

Nhiều ngôn ngữ khác không có cú pháp tương ứng cho các destructuring, rest parameters, và spread synt, vì vậy các tính năng này có thể là một sự học hỏi cho cả nhà lập trình JavaScript mới và những người đến từ ngôn ngữ khác. Trong bài viết này, bạn sẽ học cách hủy cấu trúc các đối tượng và mảng, cách sử dụng toán tử spread để giải nén các đối tượng và mảng cũng như cách sử dụng các tham số còn lại trong lời gọi hàm.

2. Destructuring

Gán hủy cấu trúc(Destructuring) là một cú pháp cho phép bạn gán các thuộc tính đối tượng hoặc các phần tử mảng dưới dạng các biến. Điều này có thể làm giảm đáng kể các dòng code cần thiết để thao tác dữ liệu trong các cấu trúc này. Có hai kiểu hủy cấu trúc: Cấu trúc đối tượng và hủy cấu trúc mảng.

Object destructuring:

Cấu trúc đối tượng cho phép bạn tạo các biến mới bằng cách sử dụng một thuộc tính đối tượng làm giá trị. Ví dụ :

const note = {
  id: 1,
  title: 'My first note',
  date: '01/01/1970',
}

// Create variables from the Object properties
const id = note.id
const title = note.title
const date = note.date

Với Object destructuring, tất cả điều này có thể được thực hiện trong một dòng. Bằng cách đặt mỗi biến trong dấu ngoặc nhọn {}, JavaScript sẽ tạo các biến mới từ mỗi thuộc tính có cùng tên:

// Destructure properties into variables
const { id, title, date } = note
console.log(id)
console.log(title)
console.log(date)

Output:
1
My first note
01/01/1970

Phép gán mặc định cho Object destructuring tạo ra các biến mới có cùng tên với thuộc tính đối tượng. Nếu bạn không muốn biến mới có cùng tên với tên thuộc tính, bạn cũng có tùy chọn đổi tên biến mới bằng cách sử dụng dấu hai chấm (:)để quyết định một tên mới,ví dụ :

// Assign a custom name to a destructured value
const { id: noteId, title, date } = note
console.log(noteId)

Output:
1

Bạn cũng có thể làm vậy với các giá trị đối tượng lồng nhau. Ví dụ:

const note = {
  id: 1,
  title: 'My first note',
  date: '01/01/1970',
  author: {
    firstName: 'Sherlock',
    lastName: 'Holmes',
  },
}

// Destructure nested properties
const {
  id,
  title,
  date,
  author: { firstName, lastName },
} = note

console.log(`${firstName} ${lastName}`)

Output:
Sherlock Holmes

Lưu ý rằng trong ví dụ này, mặc dù bạn có quyền truy cập vào nội dung của đối tượng author, nhưng bản thân đối tượng đó không thể truy cập được. Để truy cập một đối tượng cũng như các giá trị lồng nhau của nó, bạn sẽ phải khai báo chúng một cách riêng biệt:

// Access object and nested values
const {
  author,
  author: { firstName, lastName },
} = note
console.log(author)

Output
{firstName: "Sherlock", lastName: "Holmes"}

Object destructuring không chỉ hữu ích để giảm số lượng code, nó cũng cho phép bạn nhắm mục tiêu quyền truy cập của mình vào các thuộc tính mà bạn quan tâm.

Cuối cùng, destructuring có thể được sử dụng để truy cập các thuộc tính đối tượng của các giá trị nguyên thủy. Ví dụ: String

const { length } = 'A string'
console.log(length)

Output:
8

Chuỗi 'A string' đã được chuyển đổi hoàn toàn thành một đối tượng để truy xuất thuộc tính length.

Array Destructuring

Cấu trúc mảng cho phép tạo các biến mới bằng cách sử dụng một mục mảng làm giá trị. Hãy xem xét ví dụ sau:

const date = ['1970', '12', '01']

Mảng trong JavaScript được đảm bảo duy trì thứ tự của chúng, vì vậy trong trường hợp này, chỉ mục đầu tiên sẽ luôn là năm, chỉ mục thứ hai sẽ là tháng, v.v. Biết được điều này, bạn có thể tạo các biến từ các mục trong mảng:

// Create variables from the Array items
const year = date[0]
const month = date[1]
const day = date[2]

Nhưng cách thủ công này hơi dài dòng. Với cấu trúc hủy mảng (Array Destructuring), bạn có thể giải nén các giá trị từ mảng theo thứ tự và gán chúng cho các biến riêng của chúng, như sau:

// Destructure Array values into variables
const [year, month, day] = date
console.log(year)
console.log(month)
console.log(day)

Output:
1970
12
01

Có thể bỏ qua các giá trị bằng cách để trống cú pháp cấu trúc giữa các dấu phẩy:

// Skip the second item in the array
const [year, , day] = date

console.log(year)
console.log(day)

Output
1970
01

Các mảng lồng nhau cũng có thể bị hủy. Ví dụ:

// Create a nested array
const nestedArray = [1, 2, [3, 4], 5]
// Destructure nested items
const [one, two, [three, four], five] = nestedArray

console.log(one, two, three, four, five)

Output
1 2 3 4 5

Cú pháp hủy cấu trúc có thể được áp dụng với các tham số trong một hàm. Để kiểm tra điều này, bạn sẽ hủy cấu trúc keys và values trong Object.entries ():

const note = {
  id: 1,
  title: 'My first note',
  date: '01/01/1970',
}

// Using forEach
Object.entries(note).forEach(([key, value]) => {
  console.log(`${key}: ${value}`)
})

// Using a for loop
for (let [key, value] of Object.entries(note)) {
  console.log(`${key}: ${value}`)
}

Output
id: 1
title: My first note
date: 01/01/1970

Object destructuring và array destructuring có thể được kết hợp với nhau. Ví dụ :

const note = {
  title: 'My first note',
  author: {
    firstName: 'Sherlock',
    lastName: 'Holmes',
  },
  tags: ['personal', 'writing', 'investigations'],
}

const {
  title,
  date = new Date(),
  author: { firstName },
  tags: [personalTag, writingTag],
} = note

console.log(date)

Output
Fri May 08 2020 23:53:49 GMT-0500 (Central Daylight Time

Như đvậy, cú pháp gán hàm hủy cấu trúc bổ sung nhiều tính linh hoạt cho JavaScript và cho phép bạn viết code ngắn gọn hơn. Trong phần tiếp theo, bạn sẽ thấy cú pháp spread có thể được sử dụng như thế nào để mở rộng cấu trúc dữ liệu vào các mục dữ liệu cấu thành của chúng.

3. Spread

Cú pháp spread (...) là một bổ sung hữu ích khác cho JavaScript để làm việc với mảng, đối tượng và lời gọi hàm. Spread cho phép các đối tượng và các tệp lặp (chẳng hạn như mảng) được giải nén hoặc mở rộng, có thể được sử dụng để tạo các bản sao đơn giản của cấu trúc dữ liệu để dễ thao tác dữ liệu.

Spread with Arrays

Hãy cùng xem ví dụ sau về spread với mảng trong Javascript làm cho việc thao tác với mảng trở nên đơn giản hơn :

// Create an Array
const tools = ['hammer', 'screwdriver']
const otherTools = ['wrench', 'saw']

// Concatenate tools and otherTools together
const allTools = tools.concat(otherTools)

// Unpack the tools Array into the allTools Array
const allTools = [...tools, ...otherTools]

console.log(allTools)

Output
["hammer", "screwdriver", "wrench", "saw"]

Ví dụ tiếp theo :

// Array of users
const users = [
  { id: 1, name: 'Ben' },
  { id: 2, name: 'Leslie' },
]

// A new user to be added
const newUser = { id: 3, name: 'Ron' }

users.push(newUser)

const updatedUsers = [...users, newUser]

console.log(users)
console.log(updatedUsers)

Output
[{id: 1, name: "Ben"}
 {id: 2, name: "Leslie"}]

[{id: 1, name: "Ben"}
 {id: 2, name: "Leslie"}
 {id: 3, name: "Ron"}]

Tạo bản sao dữ liệu thay vì thay đổi dữ liệu hiện có có thể giúp ngăn chặn những thay đổi không mong muốn. Trong JavaScript, khi bạn tạo một đối tượng hoặc mảng và gán nó cho một biến khác, bạn không thực sự tạo một đối tượng mới — mà đang truyền một tham chiếu. Một ví dụ khác :

// Create an Array
const originalArray = ['one', 'two', 'three']

// Assign Array to another variable
const secondArray = originalArray

// Remove the last item of the second Array
secondArray.pop()
console.log(originalArray)

Output:
["one", "two"]

Spread cho phép bạn tạo bản sao đơn giản của một mảng hoặc đối tượng, có nghĩa là bất kỳ thuộc tính cấp cao nhất nào cũng sẽ được sao chép, nhưng các đối tượng lồng nhau sẽ vẫn được chuyển qua tham chiếu. Đối với các mảng hoặc đối tượng đơn giản, một bản sao có thể là tất cả những gì bạn cần. Spread cũng có thể được sử dụng để chuyển đổi một tập hợp hoặc bất kỳ tập hợp nào khác có thể lặp lại thành mảng.

// Create a set
const set = new Set()

set.add('octopus')
set.add('starfish')
set.add('whale')

const seaCreatures = [...set]
console.log(seaCreatures)

Output
["octopus", "starfish", "whale"]

Điều này cũng có thể hữu ích để tạo một mảng từ một chuỗi:

const string = 'hello'
const stringArray = [...string]
console.log(stringArray)

Output
["h", "e", "l", "l", "o"]

Spread with Objects

Khi làm việc với các đối tượng, spread có thể được sử dụng để sao chép và cập nhật các đối tượng. Ban đầu, Object.assign ()được sử dụng để sao chép một đối tượng:

// Create an Object and a copied Object with Object.assign()
const originalObject = { enabled: true, darkMode: false }
const secondObject = Object.assign({}, originalObject)

Đối tượng secondObject bây giờ sẽ là một bản sao của originalObject. Điều này được đơn giản hóa với cú pháp spread — bạn có thể sao chép đơn giản một đối tượng bằng cách truyền nó vào một đối tượng mới:

// Create an object and a copied object with spread
const originalObject = { enabled: true, darkMode: false }
const secondObject = { ...originalObject }

console.log(secondObject)

Output
{enabled: true, darkMode: false}

Cũng giống như với mảng, điều này sẽ chỉ tạo ra một bản sao đơn giản cơ bản và các đối tượng lồng nhau sẽ vẫn được chuyển qua tham chiếu.

Việc thêm hoặc sửa đổi các thuộc tính trên một đối tượng hiện có theo kiểu bất biến được đơn giản hóa với spread. Cùng xem ví dụ sau:

const user = {
  id: 3,
  name: 'Ron',
}
const updatedUser = { ...user, isLoggedIn: true }
console.log(updatedUser)

Output
{id: 3, name: "Ron", isLoggedIn: true}

Một điều quan trọng cần lưu ý với việc cập nhật các đối tượng qua spread là bất kỳ đối tượng lồng nhau nào cũng sẽ phải được spread. Ví dụ: giả sử rằng trong đối tượng user có một đối tượng organization lồng nhau:

const user = {
  id: 3,
  name: 'Ron',
  organization: {
    name: 'Parks & Recreation',
    city: 'Pawnee',
  },
}

const updatedUser = { ...user, organization: { position: 'Director' } }
console.log(updatedUser)

Output:
id: 3
name: "Ron"
organization: {position: "Director"}

Nếu khả năng thay đổi không phải là vấn đề, trường có thể được cập nhật trực tiếp:

const updatedUser = {
  ...user,
  organization: {
    ...user.organization,
    position: 'Director',
  },
}

console.log(updatedUser)

Output
id: 3
name: "Ron"
organization: {name: "Parks & Recreation", city: "Pawnee", position: "Director"}

Spread with Function Calls

Ví dụ :

// Create a function to multiply three items
function multiply(a, b, c) {
  return a * b * c
}
multiply(1, 2, 3)

Output
6

Nếu tất cả các giá trị bạn muốn chuyển cho hàm đã tồn tại trong một mảng, thì cú pháp spread cho phép bạn sử dụng từng mục trong một mảng làm đối số:

const numbers = [1, 2, 3]
multiply(...numbers)

Output
6

Lưu ý: Không có spread, có thể thay thế bằng apply ():

multiply.apply(null, [1, 2, 3])

Output
6

Bây giờ bạn đã thấy cách spread có thể rút ngắn đoạn code của bạn, bạn có thể xem cách sử dụng khác của ... cú pháp: rest parameters.

Rest parameters

Tính năng cuối cùng bạn sẽ học trong bài viết này là cú pháp rest parameter . Cú pháp xuất hiện giống như spread (...) nhưng có tác dụng ngược lại. Thay vì giải nén một mảng hoặc đối tượng thành các giá trị riêng lẻ, cú pháp còn lại sẽ tạo một mảng với số lượng đối số không xác định. Ví dụ:

function restTest(...args) {
  console.log(args)
}
restTest(1, 2, 3, 4, 5, 6)

Output
[1, 2, 3, 4, 5, 6]

Cú pháp Rest có thể được sử dụng làm tham số duy nhất hoặc tham số cuối cùng trong danh sách. Nếu được sử dụng làm tham số duy nhất, nó sẽ thu thập tất cả các đối số, nhưng nếu nó ở cuối danh sách, nó sẽ thu thập mọi đối số còn lại, như được thấy trong ví dụ này:

function restTest(one, two, ...args) {
  console.log(one)
  console.log(two)
  console.log(args)
}
restTest(1, 2, 3, 4, 5, 6)

Output
1
2
[3, 4, 5, 6]

Trong code cũ hơn, biến đối số có thể được sử dụng để thu thập tất cả các đối số được chuyển qua một hàm:

function testArguments() {
  console.log(arguments)
}
testArguments('how', 'many', 'arguments')

Output
1Arguments(3) ["how", "many", "arguments"]

Tuy nhiên, điều này có một vài nhược điểm. Đầu tiên, không thể sử dụng arguments với các arrow functions.

const testArguments = () => {
  console.log(arguments)
}
testArguments('how', 'many', 'arguments')

Output
Uncaught ReferenceError: arguments is not defined

Ngoài ra, các arguments không phải là một mảng đúng và không thể sử dụng các phương thức như map hay filter mà không được chuyển đổi trước thành một mảng. Nó cũng sẽ thu thập tất cả các đối số được truyền thay vì chỉ phần còn lại của các đối số, như đã thấy trong ví dụ restTest (một, hai, ... args).

Rest có thể được sử dụng khi cấu trúc lại mảng:

const [firstTool, ...rest] = ['hammer', 'screwdriver', 'wrench']

console.log(firstTool)
console.log(rest)

Output
hammer
["screwdriver", "wrench"]

Rest cũng có thể được sử dụng khi cấu trúc các đối tượng:

const { isLoggedIn, ...rest } = { id: 1, name: 'Ben', isLoggedIn: true }

console.log(isLoggedIn)
console.log(rest)

Output
true
{id: 1, name: "Ben"}

Theo cách này, cú pháp rest cung cấp các phương pháp hiệu quả để thu thập một lượng mục không xác định.

Kết luận

Trong bài viết này, bạn đã tìm hiểu về destructuring, spread syntax, và rest parameters :

  • Destructuring được sử dụng để tạo các biến thể từ các phần tử mảng hoặc thuộc tính đối tượng.
  • Cú pháp Spread được sử dụng để giải nén các tệp lặp lại như mảng, đối tượng và lời gọi hàm.
  • Cú pháp Rest parameter sẽ tạo một mảng từ một số lượng giá trị không xác định.

Destructuring, spread syntax, và rest parameters là những tính năng hữu ích trong JavaScript giúp giữ cho đoạn code của bạn ngắn gọn và sạch sẽ.

Nguồn : https://www.digitalocean.com/community/tutorials/understanding-destructuring-rest-parameters-and-spread-syntax-in-javascript


All Rights Reserved