---
description: >-
  https://learnreac.gitbook.io/project/object-for-three-dots-array-for-three-dots-ok
---

# "... Three Dots" đã thay đổi javascript như thếnào ?

"Three dots" là một khái niệm cực kì khó nhai cho những ai mới bắt đầu nguyên cứu về những tính năng mới của ES6, three dots hay còn gọi với cái tên là "**spread syntax**". Tại sao ES6 lại đưa **syntax** mới đầy mạnh mẽ này vào. Sau nhiều ngày mày mò tìm hiểu, mình quyết định chia sẽ bài viết này để chia sẽ với mọi người để cho mọi người hiểu hơn về syntax này. Chúng ta hãy được vấn đề khi chưa có "syntax" này nhé. Như các bạn đã biết khi làm việc với "**agruments**" object. Thật ra **agruments** là một biến cục bộ trong function, chứa toàn bộ các tham số được truyền vào. Các bạn xem ví dụ để hiểu hơn về vai trò của **arguments**. Ở đây mình sẽ đưa ra 2 ví dụ mà ES5 xử lý thông thường.

**Kịch bản 1**: In ra tất các các tham truyền vào:

```
function display(){
    // arguments is an array-like object
    var args = Array.apply(null, arguments);
    console.log(args); // [1, 2, 3]
}
display(1, 2, 3)
```

Arguments is **an array-like object**. Thật ra arguments là **một object giống array nhưng không phải là array**. Tại sao lại kì quặc như vậy, **arguments** có phương thức length, ta có thể gọi value bằng chỉ số index 1,2,3... Nhưng ta không thể gọi được các phương thức của array, vì do không có prototype là array =)). Khi làm việc với arguments thật không dễ chịu tí nào, ta phải chuyển arguments object thành array rồi mới sử dụng được các method của array bằng cách `Array.apply(null, arguments)`. Thật phiền phải không nào

**Kịch bản 2**: Concat hai array với nhau Đây là cách mà ES5 sử lý vấn đề này:

```
var fruits = ['banana'];  
var moreFruits = ['apple', 'orange'];  
Array.prototype.push.apply(fruits, moreFruits);  
console.log(fruits); // => ['banana', 'apple', 'orange'] 
```

Kết quả như kì vọng của chúng ta. Vấn đề ở đây là ta "mượn hàm" của array qua thông prototype, rồi gọi push method, rồi gọi đến apply..Cách tiếp cận này khá rườm rà. Với sự ra đời của "... three dots" đã giải quyết 2 vấn đề thường gặp của chúng ta nhưng thế nào nhé

## Three dots <a href="#three-dots-0" id="three-dots-0"></a>

#### The rest operator <a href="#the-rest-operator-1" id="the-rest-operator-1"></a>

**The rest operator** được sử dụng lấy tất cả các tham số tryền vào, chúng ta giải quyết kịch bản 1 như thế nào nhé

```
function display(...args) {  
   console.log(args);
}
display('welcome', 'to', 'Earth'); // => ['welcome', 'to', 'Earth']
```

Ở đây args là array. Args này có prototype là array => sẽ sử dụng đầy đủ tính năng của array. Gọn hơn rất nhiều phải không ? Với tham số **...args** của display method chúng ta nhận bao nhiêu đối số cũng được, hay nói cách khác là chúng ta có thể "spread" các tham số truyền vào.

#### The spread operator <a href="#the-spread-operator-2" id="the-spread-operator-2"></a>

**The spread operator** được sử dụng cho array construction and [destructuring](https://viblo.asia/vinhnguyen/posts/xlbRBNQgRDM) => chúng ta sẽ giải quyết problem ở kịch bản 2 như sau

```
let cold = ['autumn', 'winter'];  
let warm = ['spring', 'summer'];  
// construct an array
[...cold, ...warm] // => ['autumn', 'winter', 'spring', 'summer']

// function arguments from an array
cold.push(...warm);  
cold              // => ['autumn', 'winter', 'spring', 'summer']  
```

Three dots còn làm được nhiều điều hơn nữa. Khi chúng ta khởi tạo new Date (), thì chúng ta không thể inject array vào constructor của Object Date được. Nhưng với three dots thì có thể làm được điều đó

```
var dateFields = [1970, 0, 1];  // 1 Jan 1970
var d = new Date(...dateFields);
```

#### Inject params to constructor <a href="#inject-params-to-constructor-4" id="inject-params-to-constructor-4"></a>

Với Class là một tính năng được ES6 giới thiệu, với "spread syntax" ta có thể thiết lập được param của constructor một cách nhanh chóng, khi mà chúng ta k thể gọi arguments trong constructor được =))

```
class King {  
   constructor(name, country) {
     this.name = name;
     this.country = country;     
   }
   getDescription() {
     return `${this.name} leads ${this.country}`;
   }
}
var details = ['Alexander the Great', 'Greece'];  
var Alexander = new King(...details);  
Alexander.getDescription(); // => 'Alexander the Great leads Greece' 
```

#### Quickly initial elements from another array <a href="#quickly-initial-elements-from-another-array-5" id="quickly-initial-elements-from-another-array-5"></a>

Speard operator thật mạnh mẽ, nó có thể khởi tạo `array literal` từ array khác nữa nó. Hãy xem cách "..." thực hiện điều này như thế này nhé

```
var initial = [0, 1];  
var numbers1 = [...initial, 5, 7];  
console.log(numbers1); // => [0, 1, 5, 7]  
let numbers2 = [4, 8, ...initial];  
console.log(numbers2); // => [4, 8, 0, 1] 
```

#### Array destructure <a href="#array-destructure-6" id="array-destructure-6"></a>

Destructuring assignments là một tính năng rất thú vị của ES6, đây là một phương thức khá khó tiêu, nó giúp mình tách data từ array hoặc object, nó rất giống với method list của php =)). Các bạn có thể đọc thêm bài viết này để học hỏi thêm nha [https://viblo.asia/vinhnguyen/posts/xlbRBNQgRDM](https://viblo.asia/vinhnguyen/posts/xlbRBNQgRDM)

```
var seasons = ['winter', 'spring', 'summer', 'autumn'];  
var coldSeason, otherSeasons;  
[coldSeason, ...otherSeasons] = seasons;
console.log(coldSeason);   // => 'winter'  
console.log(otherSeasons); // => ['spring', 'summer', 'autumn'] 
```

## Finale <a href="#finale-7" id="finale-7"></a>

Qua bài viết này mình đã giới thiệu "three dots" sinh ra để giải quyết vấn đề "arguments" object rườm rà khi nhận giá trị từ param inject vào, việc sử dụng "spread syntax" sẽ làm cho code của chúng ta trở nên clear hơn rất nhiều, qua đây mà sẽ improve khi thao tác với **array literals** như là khởi tạo, clone, concatenate... và Destructuring bằng cách sử dụng "spread operator". Đối với mình "three dots" rất tuyệt đấy. Happy coding =))
