JavaScript là một ... ngôn ngữ ... thú vị. Cá nhân tôi (Grant Sander) thích nó, nhưng có thể thấy tại sao những người khác lại không thích nó. ECMAScript 6, a.k.a. ES6, đã giới thiệu một số tính năng thực sự tuyệt vời giúp phát triển JavaScript thú vị hơn. Trong bài viết ngắn này, tôi muốn nói một chút về destructuring assignment và cung cấp một số ví dụ thực tế, điều này có thể hữu ích.
MDN mô tả destructuring assignment theo cách sau:

  • Cú pháp destructuring assignment  là một biểu thức JavaScript có thể giải nén các giá trị từ các mảng, hoặc các thuộc tính từ các đối tượng, thành các biến riêng biệt.
Điều này có nghĩa là bạn có thể lấy một mảng hoặc đối tượng, và dễ dàng lấy ra các giá trị từ nó và gán chúng cho các biến.

Destructuring Assignment với Objects

Giả sử bạn có một đối tượng biểu diễn một điểm trong không gian 3 chiều:
let myPointInSpace = {
  x: 3,
  y: -2,
  z: 2.7
}

Giả sử bạn muốn thực hiện một số tính toán với tọa độ của điểm [như tính toán khoảng cách của nó từ gốc, (0, 0, 0)], vì vậy bạn muốn ném tọa độ x, y và z của điểm vào một số biến để dễ tham khảo. Người ta có thể làm như sau:

let x = myPointInSpace.x;
let y = myPointInSpace.y;
let z = myPointInSpace.z;

let distance = Math.sqrt(x*x + y*y + z*z);

Điều này chắc chắn hoạt động! Nhưng nếu bạn làm điều đó đủ thời gian, bạn có thể bị bệnh sao chép / dán. Với destructuring assignment, bạn có thể nhổ những tọa độ đó theo một cách ngắn gọn hơn nhiều! Dưới đây là cách thực hiện:

let {x, y, z} = myPointInSpace;

let distance = Math.sqrt(x*x + y*y + z*z);

Các dấu ngoặc nhọn trong trường hợp này chỉ ra destructuring assignment. Dòng đầu tiên ở trên nhìn vào biến myPointInSpace và tìm kiếm bất kỳ thuộc tính nào được chỉ định trong dấu ngoặc nhọn và sẽ trả về các biến đó trong các phép gán biến riêng lẻ.

Thuận tiện, bạn chỉ có thể lấy một tập con của thuộc tính-giá trị của đối tượng. Ví dụ, nếu bạn chỉ cần tọa độ x và y, bạn cũng có thể thực hiện:
let {x, y} = myPointInSpace;

 

Destructuring Assignment với Arrays

Destructuring assignment là tuyệt vời khi được sử dụng với các đối tượng, nhưng nó cũng có thể được sử dụng với các mảng theo cách tương tự. Giả sử rằng điểm của chúng ta trong không gian được biểu diễn dưới dạng 3-tuple (hoặc mảng của 3 giá trị).
 
Cách học cũ của việc ném tọa độ của điểm này là:
let x = myPointInSpace[0];
let y = myPointInSpace[1];
let z = myPointInSpace[2];
Với destructuring assignment, chúng tôi có thể rút ngắn việc này thành:
let [x, y, z] = myPointInSpace;

Khá gọn gàng!

Một số ví dụ thực tế

Tôi đọc về destructuring assignment một vài lần trước khi tôi thực sự sử dụng nó và đánh giá cao tiện ích của nó. Tôi đã cho thấy một ví dụ đơn giản ở trên chỉ liên quan đến các giá trị đơn giản, nhưng tôi muốn giới thiệu một vài ví dụ hữu ích hơn

Đặt giá trị hàm mặc định

Khi viết các hàm, tôi thường thích sử dụng một đối tượng đơn lẻ làm đầu vào, và sau đó kéo các giá trị từ đối tượng đó - theo cách đó tôi không phải lo lắng về thứ tự các đầu vào của mình. Destructuring assignment giúp với điều này và cho phép chúng tôi sử dụng "các tham số mặc định" được giới thiệu trong ES6.
Giả sử bạn muốn viết một hàm mất một số giờ, phút và giây và chuyển đổi lượng thời gian đó thành một số mili giây. Chúng tôi có thể làm điều này thông qua những điều sau đây:
let toMilliseconds = ({
  hours = 0,
  minutes = 0,
  seconds = 0
}) => {
  // Compute the # of ms
  let ms = (hours * 60 * 60 * 1000) + (minutes * 60 * 1000) + (seconds * 1000);
  // Return the # of ms
  return ms;
}
 
Điều này có thể trông giống như một khai báo hàm lạ, nhưng nó đòi hỏi rằng chúng ta có thể truyền vào một đối tượng làm đầu vào cho toMilliseconds () và hàm sẽ tìm kiếm các khóa giờ, phút và giây để sử dụng. Nếu nó không tìm thấy bất kỳ khóa nào trong số các khóa đó trong đối tượng được truyền vào, nó sẽ chỉ mặc định là 0. Đặt nó để sử dụng có thể trông giống như sau:
let ms1 = toMilliseconds({hours: 3, minutes: 42, seconds: 33});
let ms2 = toMilliseconds({minutes: 7});
 
Trong dòng thứ hai ở trên, giờ và giây được mặc định là 0 và chúng tôi không phải truyền một cách rõ ràng một số giờ hoặc giây.
Tôi đã phát triển như thế này bằng cách viết các hàm, vì một số hàm có rất nhiều tham số mà tất cả đều cần mặc định - và dạng khai báo hàm này có thể đọc được với tôi.

Trao đổi giá trị

Trao đổi các giá trị của biến là một thủ tục khá phổ biến, và thường liên quan đến việc tạo ra một biến tạm thời. Đây là một ví dụ điển hình về điều này.

// Initial values
let x = 5;
let y = 3;

// Now swap, creating tmp variable
let tmp = y;
y = x;
x = tmp;
delete tmp;
Tuy nhiên, destructuring assignment làm cho điều này gọn gàng hơn, và theo ý kiến ​​của tôi, một chút dễ đọc hơn:
// Initial values
let x = 5;
let y = 3;

// Now swap
[x, y] = [y, x];

Nếu bạn thấy mình trao đổi các biến thường xuyên, destructuring có thể là một công cụ thực sự tốt đẹp.

Kéo giá trị và đặt tên mới

Với destructuring đối tượng, bạn thực sự có thể đặt tên cho các biến của mình ngoài các khóa của đối tượng mà bạn đang destructuring. Giả sử bạn đang sử dụng một API, và API gửi trả lời một đối tượng mà đối tượng có tên lạ mà bạn không thích sử dụng. Một cái gì đó như sau:

let apiResponse = {
  someWeirdKeyForX: 3,
  someWeirdKeyForY: -7
}
Chúng ta có thể kéo các giá trị x và y ra khỏi phản hồi đó và đặt tên chúng là bất cứ điều gì chúng ta muốn - nói x và y. Để làm điều này, chúng tôi sử dụng cú pháp sau:
let {someWeirdKeyForX: x, someWeirdKeyForY: y} = apiResponse;

Phần someWeirdKeyForX: x của destructuring tuyên bố rằng bạn muốn kéo khóa someWeirdKeyForX từ apiResponse và bạn muốn gán nó cho một biến có tên là x. Điều này có thể hữu ích đáng ngạc nhiên. Thực tế, tôi thích sử dụng điều này trong các tình huống đơn giản như gán một cái gì đó như apiResponse.latitude cho lat và apiResponse.longitude cho lng.

Coi chừng!

Một chút "gotcha" mà tôi vấp vào một vài lần là một thực tế là đôi khi bạn cần phải quấn các destructuring statements của bạn trong dấu ngoặc đơn. Nếu destructuring statements của bạn không bắt đầu với một từ khóa khai báo biến (như var, let, hoặc const), bạn sẽ cần bọc câu lệnh của bạn trong dấu ngoặc đơn. Tôi giả sử điều này là để trình biên dịch biết cách phân biệt giữa {...} trong câu lệnh hủy và {...} chỉ ra các khối mã.

Đây là những gì tôi có ý nghĩa của điều này. Xem xét mã sau:
// Declare x and y ahead of time
let x, y;
// Object that we will destructure
let o = {x: 3, y: -7};

// Try to destructure
{x, y} = o; // -> No good!

Trình biên dịch không biết cách diễn giải dòng mã cuối cùng đó. Bạn sẽ cần phải thay đổi nó thành:

// Declare x and y ahead of time
let x, y;
// Object that we will destructure
let o = {x: 3, y: -7};

// Successfully destructure
({x, y} = o); // -> Good!
Nếu bạn thấy mình sử dụng destructuring, hãy chắc chắn rằng bạn nhận thức được điều này !

 Và hơn thế!

MDN có nhiều ví dụ về việc destructuring assignment hơn. Nếu bạn muốn biết thêm, hãy kiểm tra trang đó. Trong bài tiếp theo của tôi, chúng ta sẽ đi sâu vào phần còn lại và phát tán các toán tử trong Javascript, và xem cách chúng chơi thành destructuring assignment.

Bài dịch từ trang https://dev.to/gksander/destructuring-assignment-in-javascript-1ace .

Xin cảm ơn các bạn đã theo dõi bài viết của Nguyên Vũ.