Destructuring là 1 kỹ thuật được giới thuật trong ES6, giúp cho việc sao chép, trích xuất lại các variable
1 cách rất rõ ràng, dễ hiểu hơn rất nhiều so với những cách thông thường khác và chắc chắn là code line
cũng giảm đi đáng kể.
Destructuring là gì? Tôi hiểu như này, destructuring là cấu trúc và khi ta thêm tiền tố de vào trước thành destructuring nghĩa sẽ chuyển thành phá hủy cấu trúc, tôi luôn cố gắng hiểu các thuật ngữ tiếng anh 1 cách thuần túy, bám sát với nghĩa gốc tiếng anh của chúng như thế. Những cách đặt tên những thuật ngữ trong lập trình cũng chính là dựa vào chức năng, nhiệm vụ của nó mà ta đặt tên thôi.
Giống như hàm filter(tạm dịch: lọc) của Array - nhiệm vụ của nó đơn giản là lặp qua lần lượt các element
của mảng và lọc những element
nào thỏa điều kiện. Hay khái niệm inheritance
(nghĩa: thừa kế) trong OOP, vì đơn giản là nó có thể dùng lại những variable
hay method
của parent
chúng, như ta thoải mái tiêu tiền của cha mẹ ta thôi hihi.
Tại sao tôi lại đi vào giải thích kỹ định nghĩa destructuring như vậy, vì hiểu được tên gọi của nó là ta đã hiểu được 1 phần nào cách mà nó hoạt động. Chính là từ 1 structure
có sẵn, nó phá hủy structure đó, extract những properties
ra và biểu diễn lại theo structure
mà mình muốn.
Destructuring trong Javascript dùng rất nhiều khi làm việc với array và object, phần này chúng ta sẽ cùng nhau tìm hiểu trong giới hạn array thôi nhé!
Ta hãy cùng so sánh 2 đoạn code dưới đây:
var [first, second, third] = ["Laide", "Gabriel", "Jets"];
Khi sử dụng destructuring
var first = "laide",
second = "Gabriel",
third = "Jets";
Và khi không sử dụng
Rõ ràng là ta hơn được 2 điểm readiable
và line code
rồi đúng không.?!? Nhưng hãy chú ý 1 điều nho nhỏ là:
Ta không được dùng
Number
khi làm việc vớidestructuring
. Number sẽ tạo raerror
ngay vì chúng không phải làvariable name
var [1, 2, 3] = ["Laide", "Ola", "Jets"];
Đoạn code này sẽ sinh ra lỗi
*Destructuring trích xuất dữ liệu từ 1 array rất dễ dàng và dễ nhìn phải không? Thử tượng tượng rằng nếu phải ta có 1 array với 5, 6 levels thì làm theo cách thông thường sẽ mất thời gian và bớt cool ngầu hơn thế nào, Ta chỉ cần dùng 1 array literal bên phía trái cho việc gán này.
var thing = ["Table", "Chair", "Fan"];
var [a, b, c] = thing;
Destructuring làm nhiệm vụ lấy từng var
trong array literal bên phía trái và map
chúng với element
tương ứng cùng vị trí trong mảng array bên phải.
console.log(a); // Output: Table
console.log(b); //Output: Chair
console.log(c); //Output: Fan
Nếu số lượng var
được truyền vào destructuring array literal ** lớn hơn** số element
của arr phía bên phải, thì những var
không được map
đó sẽ return undefined
var things = ["Table", "Chair", "Fan", "Rug"];
var [a, b, c, d, e] = things;
console.log(c); //Output: Fan
console.log(d); //Output: Rug
console.log(e); //Output: undefined
Còn trường hợp ngược lại - ít hơn thì chẳng có gì xảy ra cả, chúng vẫn sẽ được map lần lượt và tương ứng thôi
Destructuring giúp làm việc với function mà return 1 array chính xác hơn nhiều. Ví dụ:
function runners(){
return ["Sandra", "Ola", "Chi"];
}
var [a, b, c] = runners();
console.log(a); //Output: Sandra
console.log(b); //Output: Ola
console.log(c); //Output: Chi
Destructuring cho phép 1 default value
được assigned
với var
mà không có value
gì hay undefined
được truyền vào. Giống như việc ta có 1 bản dự phòng nếu không có 1 giá trị nào được truyền vào.
var a, b;
[a = 40, b = 4] = [];
console.log(a); //Output: 40
console.log(b); //Output: 4
[a = 40, b = 4] = [1, 23];
console.log(a); //Output: 1
console.log(b); //Output: 23
Default value
còn có thể tham chiếu tới những var
có trong cùng array literal với nó
var [first = "Cotlin", second = first] = [];
console.log(first); //Output: Cotlin
console.log(second); //Output: Cotlin
var [first = "Cotlin", second = first] = ["Koku"];
console.log(first); //Output: Koku
console.log(second); //Output: Koku
var [first = "Cotlin", second = first] = ["Koku", "Lydia"];
console.log(first); //Output: Koku
console.log(second); //Output: Lydia
Ta chỉ việc bỏ element
mà ta không muốn map giữa 2 dấu phẩy , ,
là được
var a, b;
[a, , b] = ["Lordy", "Crown", "Roses"];
console.log(a); //Output: Lordy
console.log(b); //Output: Roses
1 operator (...)
mới được thêm vào trong ES6 có thể dùng trong destructuring . Nếu (...)
operator xuất hiện phía bên trái khi dùng destructuring thì nó gọi là REST PARAMETER.
Dừng lại 1 chút, ta lại cùng nhau mổ xẻ thuật ngữ rest
là gì. Bạn thử coppy và paste vào google translate xem ... vâng nó nghĩa "nghỉ ngơi, nằm ngủ, ..." đúng là như vậy. Đùa chút thôi, thực ra còn 1 nghĩa khác nữa, hay trong lập trình ta hiểu nó là: phần còn lại
1 rest parameter
được dùng để map những element
trong arr mà chúng không được map với gì cả. Như là việc ta gói những element
bị bỏ lại và map chúng với rest parameter
này. Chú ý rest parameter
phải đứng ở cuối nêú không thì sẽ xuất hiện 1 lỗi syntax
.
var planets = ["Mercury", "Earth", "Venus", "Mars", "Pluto", "Saturn"];
var [first, , third, ...others] = planets;
console.log(first); //Output: Mercury
console.log(third); //Output: Venus
console.log(others); //Output: ["Mars", "Pluto", "Saturn"]
Bây giờ nếu (...)
operator xuất hiện phía bên phải thì sao? Ta hãy cùng xem ví dụ dưới đây:
var planets = ["Mercury", "Earth", "Venus", "Mars", "Pluto", "Saturn"];
var [first, second, ...rest] = ["Mercury", "Earth", ...planets, "Saturn"];
console.log(first); //Output: Mercury
console.log(second); //Output: Earth
console.log(rest); //Output: ["Mercury", "Earth", "Venus", "Mars", "Pluto", "Saturn", "Saturn"]
Các bạn có đoán được tại sao không? Chúng ta sẽ đi từ từ từng bước 1 nhé:
- Khi ta dùng
...planets
thì bây giờ array phía phải sẽ trở thành:[Mercury", "Earth", "Mercury", "Earth", "Venus", "Mars", "Pluto", "Saturn", "Saturn"];
Và vì 2element
đầu đã được map với first, second trong destructuring, nên lúc nàyrest parameter
sẽ map nhữngelement
"bị bỏ lại" - không được map, đó chính là kết quả của output.
Destructuring còn có thể dùng để tráo đổi 2 giá trị của 2 biến
var a, b;
[a, b] = ["Male", "Female"];
[a, b] = [b, a];
console.log(a); //Output: Female
console.log(b); //Output: Male
Bạn cũng có thể sử dụng nested destructuring với arrays. Các item tương ứng cũng phải là 1 array để khiến nested destructuring array literal gán những item
tương ứng với các var
khác, ví dụ:
var places = ["first", "second", "third", "fourth"];
var [a, b, , d] = [f, ...rest] = places;
console.log(a); //Output: first
console.log(d); //Output: fourth
console.log(f); //Output: first
console.log(rest); //Output: ["second", "third", "fourth"]
Giả sử bạn đang viết 1 module getPosition
: returns vị trí hiện tại của nhân vật này - đó là 1 cặp tọa độ (x, y)
Chúng ta sẽ giải bài toán này với array destructuring:
- Khi bạn gọi
getPosition
function, bạn sẽ có 1 array với index 0 là tọa độ x, và index 1 là tọa độ y(coordinate = [x, y])
- Hãy cùng xem khi ta phối hợp function này với destructuring assignment ra sao nhé:
function getDistance(position1, position2) {
const [ x1 = 0, y1 = 0 ] = position1;
const [ x2 = 0, y2 = 0 ] = position2;
return [ x2 - x1, y2 - y1];
}
const position1 = [2, 4];
const position2 = [5, 3];
const [xDistance, yDistance] = getDistance(position1, position2);
// Should log 3
console.log(xDistance);
// Should log -1
console.log(yDistance);
Nhìn rất là dễ hiểu đúng không, số code lines của bạn còn có thể ngắn hơn nữa nếu bạn dùng destructuring ở danh sách các arguments của function này
function getDistance([x1 = 0, y1 = 0], [x2 = 0, y2 = 0]) {
return [ x2 - x1, y2 - y1];
}
const position1 = [2, 4];
const position2 = [5, 3];
const [xDistance, yDistance] = getDistance(position1, position2);
// Should log 3
console.log(xDistance);
// Should log -1
Giải thích:
[x1 = 0, y1 = 0]
: Đoạn code này đơn giản là bạn muốn 1 array với 2 positions. Vàindex 0 = x1
,index 1 = x2
. Trong trường hợp parameters truyền vào có ít hơn 2 giá trị, hoặc empty, thì x1 và x2 sẽ được gán = 0. Chú ý rằng bạn có thể truyền vào 1 empty array chứ không được omit nó, không là bug ngay!const [xDistance, yDistance] = getDistance(position1, position2)
: Đoạn code này nghĩa là functiongetDistance
sẽ return an array. Thay vì lưu array này trong 1variable
, thì bạn đã assign index 0 và 1 vào trongxDistance
vàyDistance
1 cách lần lượt rồi.
Hay chỉ đơn giản là bạn muốn get dữ liệu 1 cách tường minh, nhanh chóng hơn:
const books = [
{ name: 'Trà hoa nữ', author: 'Alexandre Dumas con', type: 'novel'},
{ name: 'Đắc nhân tâm', author: 'Dale Carnegie', type: 'novel'},
{ name: 'Tôi thấy hoa vàng trên cỏ xanh', author: 'Nguyễn Nhật Ánh', type: 'short story'}
]
const [ book1, , book3 ] = books;
console.log(book3) // expected: { name: 'Tôi thấy hoa vàng trên cỏ xanh', author: 'Nguyễn Nhật Ánh', type: 'short story'}
const [...coppyBooks] = books;
console.log(coppyBooks) // expected: = books array
Việc sử dụng được thành thạo destructuring sẽ khiến cho đoạn code của bạn trông khoa học hơn cũng như nhanh hơn rất nhiều so với những cách thông thường. Qua các phân tích trên, hãy nhớ những ý chính sau, bạn có thể sử dụng destructuring khi:
- Tạo ra những
var
mới tương ứng từ 1arr
cho trước - Tạo ra 1
coppy arr
khi phối hợp destructuring với spread operator - Tráo đổi
value
của cácvar
- Đơn giản hóa việc lấy
value
để assign vào nhữngvar
mình muốn từ cácelement
của 1 array cho trước
Bài viết có tham khảo từ các blog sau:
- https://medium.freecodecamp.org/array-destructuring-in-es6-30e398f21d10
- https://medium.com/@codingsam/awesome-javascript-destructuring-assignment-55fd2e9d3dc4
Tài liệu tham khảo thêm về destructuring: