---
# System prepended metadata

title: JS

---

# JAVASCRIPT CƠ BẢN

*JavaScript là một ngôn ngữ kịch bản hướng đối tượng, đa nền tảng, được sử dụng để giúp cho các trang Web có tính tương tác với người dùng. Ngoài ra còn có các phiên bản JavaScript phía máy chủ nâng cao hơn như Node.js, cho phép thêm nhiều chức năng vào trang Web hơn. JavaScript là một ngôn ngữ lập trình phổ biến có tính ứng dụng cao. Ngày nay, JavaScript được sử dụng trong nhiều lĩnh vực khác như phát triển phía máy chủ, phát triển ứng dụng di động,....*


## Biến
- Khai báo biến: có thể dùng `var` hoặc `let`
```javascript
var a;
let b;
```
- Khởi tạo biến:
```javascript
var a;
a = 100;
//hoặc có thể khai báo
var a = 100;
```


### Quy tắc đặt tên biến
- Tên biến không được bắt đầu bằng chữ số.
- Tên biến phải bắt đầu bằng chữ cái, hoặc dấu gạch dưới _ hoặc ký hiệu đô la $.
```javascript
var a = 100;
var _a = 100;
var $a;
```
- JavaScript có phân biệt chữ hoa và chữ thường. 
```javascript
var a;
var A;
```
- Các từ khóa trong JavaScript không thể được đặt làm tên biến.

**Note:** Tên biến thường được viết theo cách camelCase nếu nó kết hợp nhiều từ khác nhau, tức là từ đằng sau sẽ được viết hoa chữ cái đầu.
### So sánh `var` và `let`

|` var `                                                       |` let      `                                                               |
| ---------------------------------------------------------- | ----------------------------------------------------------------------- |
| Được sử dụng trong các phiên bản trước của JavaScript. | Được sử dụng để khai báo các biến từ ES6 (ES2015). |
| Có phạm vi của hàm| Có phạm vi trong một khối lệnh |
|Không cho phép khai báo lại các biến|Cho phép khai báo lại các biến|
|không hỗ trợ cơ chế hoisting|Có hỗ trợ cơ chế hoisting|


### Chú thích
// - Chú thích trên một dòng.
/ * * / - Chú thích trên nhiều dòng.

Note: Sử dụng phím tắt `Ctrl + /` cho Windows và phím tắt `Cmd + /` là dành cho Mac để dùng chú thích

## Một số hàm built-in
### console.log()
console.log() được sử dụng để in ra thông báo tới các màn hình 

Ta có thể mở một trình duyệt Web Chrome lên, sau đó nhấn nút F12. Ta nhấp chuột tới thanh có chữ "console" và bắt đầu thực hiện viết các đoạn mã Javascript và thực thi trên đó.

![](https://hackmd.io/_uploads/HkOo4cGgT.png)

- console dùng để in ra giá trị lưu trong biến
![](https://hackmd.io/_uploads/H1-Av9zea.png)
Kết quả
![](https://hackmd.io/_uploads/BkdgOcfeT.png)

### alert()
Hàm `alert()` có nhiệm vụ in một thông báo popup, nó có một tham số truyền vào và tham số này chính là nội dung ta muốn thông báo với người dùng.

![](https://hackmd.io/_uploads/HkdCRWQxp.png)

### confirm()
- Hàm `confirm()` cũng sẽ xuất hiện một thông báo popup nhưng nó có thêm hai sự lựa chọn là Yes và No, nếu người dùng chọn Yes thì nó trả về TRUE và ngược lại nếu chọn NO thì nó sẽ trả về FALSE.
- Nó cũng có một tham số truyền vào và tham số này chính là nội dung thông báo.

![](https://hackmd.io/_uploads/H17p1MQea.png)

### prompt()
Hàm `prompt()` dùng để lấy thông tin từ người dùng, gồm có hai tham số truyền vào là nội dung thông báo và giá trị ban đầu. Nếu người dùng không nhập vào thì giá trị nó sẽ trả về là NULL.

![](https://hackmd.io/_uploads/SkAHlzXla.png)


## Kiểu dữ liệu
![](https://hackmd.io/_uploads/rkFnJhGlT.png)

### String
Kiểu chuỗi ký tự được sử dụng để lưu trữ dữ liệu ở dạng văn bản. Trong Javascript, các chuỗi được bao quanh bởi dấu nháy gồm:

- Dấu ngoặc đơn
- Dấu ngoặc kép
- Dấu huyền
```javascript=
var a = 'hello'
var a = "hello"
var a = `hello`
```
**Note:** 
- Dấu nháy đơn và dấu nháy kép trên thực tế là giống nhau và ta có thể sử dụng một trong hai.
- Dấu huyền thường được sử dụng khi cần bao gồm các biến hoặc biểu thức khác vào trong một chuỗi ký tự. Điều này được thực hiện bằng cách bao bọc các biến hoặc biểu thức với ký hiệu dấu ${}.

### Number
Kiểu dữ liệu số đại diện cho các dữ liệu ở dạng số nguyên, số thực, số thập phân và số mũ.

```javascript
const a = 1;
```
Một kiểu dữ liệu số cũng có thể nhận giá trị là + Infinity, -Infinity hoặc NaN (không phải là số).
![](https://hackmd.io/_uploads/rk4VGhGeT.png)

### BigInt
- Kiểu dữ liệu số chỉ có thể đại diện cho các số nhỏ hơn (2^53 - 1) và lớn hơn - (2^53 - 1). Tuy nhiên, nếu ta cần sử dụng một kiểu dữ liệu ở dạng số lớn hơn như vậy, ta có thể sử dụng kiểu dữ liệu BigInt.
- Kiểu dữ liệu số BigInt được sử dụng bằng cách thêm `n` vào cuối một số nguyên.
- Ví dụ
```javascript=
var a = 900719925124740998n;
var b = a + 1n;
console.log(b);
```
Kết quả:
```javascript
900719925124740999n
```
### Boolean
- Kiểu dữ liệu này đại diện cho các thực thể Logic. Boolean đại diện cho một trong hai giá trị bao gồm true (đúng) hoặc false (sai).
-  Ví dụ:
```javascript
const a = true;
const b = false;
```
### undefined
Kiểu dữ liệu không xác định đại diện cho giá trị không được gán cho một biến nào đó. Nếu một biến được khai báo nhưng giá trị không được gán, thì giá trị của biến đó sẽ là `undefined` (hay không được xác định).
```javascript
var a;
console.log(a);
//hoặc
var a = undefined;
console.log(a);
```
Kết quả
```javascript
undefined
```
### null
`null` là một giá trị đặc biệt đại diện cho giá trị rỗng hoặc không xác định.
```javascript
const a = null; // a có giá trị rỗng (hay null)
```
**Note:** null không giống với NULL hoặc Null.

### Symbol
Symbol là một giá trị căn bản, có tính bất biến và có tính duy nhất.
```javascript=
var id = Symbol('id')
```
### Object
Object là một kiểu dữ liệu phức hợp, cho phép chúng ta lưu trữ các tập hợp dữ liệu.

```javascript=
var product = {
    name: 'Book',
    Price: 10,
    ID: 1002
};
```
Kết quả
![](https://hackmd.io/_uploads/SkIx2AfeT.png)



## Toán tử 

### Toán tử số học
Được sử dụng để thực hiện các phép tính số học.


| Toán tử | Mô tả | Ví dụ|
| -------- | -------- | -------- |
| +   | phép cộng   | a + b |
|-|phép trừ|a - b|
|*|phép nhân|a*b|
|**|lũy thừa|a ** b|
|/|phép chia|a/b|
|%|phép chia lấy dư|a%b|
|++|tăng lên 1 đơn vị|a++ hoặc ++a|
|--|trừ đi 1 đơn vị|a-- hoặc --a|

Ví dụ
![](https://hackmd.io/_uploads/BJpIRcGg6.png)

Kết quả:
![](https://hackmd.io/_uploads/B1-K0cGxp.png)

**Note:** Toán tử hậu tố và tiền tố có sự khác biệt (`--`;`++`)

![](https://hackmd.io/_uploads/rJ0z7iGga.png)

![](https://hackmd.io/_uploads/r1H-NjMxa.png)

### Toán tử gán
Được sử dụng để gán giá trị cho các biến.
```javascript=
let a = 1;
```
![](https://hackmd.io/_uploads/SyLCs9flT.png)
 
### Toán tử chuỗi
Có thể sử dụng toán tử + để nối (thực hiện phép nối) hai hoặc nhiều chuỗi ký tự.

![](https://hackmd.io/_uploads/Sk1mYifga.png)

**Note:**  Khi toán tử `+` được sử dụng với các chuỗi, nó sẽ thực hiện phép nối các chuỗi. Tuy nhiên, khi toán tử` +` được sử dụng với các số, nó sẽ thực hiện phép cộng.
### Toán tử so sánh
Các toán tử so sánh sẽ thực hiện so sánh hai giá trị và trả về một giá trị kiểu dữ liệu Boolean, true (đúng) hoặc false (sai).

![](https://hackmd.io/_uploads/H1g5YiGgT.png)
 
 Ví dụ
 ![](https://hackmd.io/_uploads/BJI0cozxa.png)

### Toán tử logic
Các toán tử Logic thực hiện các phép toán Logic và trả về một giá trị kiểu dữ liệu Boolean, true (đúng) hoặc false (sai).


|Toán tử | Mô tả | Ví dụ|
| -------- | -------- | -------- |
| &&     | Trả về true nếu cả 2 biểu thức đều đúng     | a && b    |
|ll |Trả về true nếu 1 trong 2 biểu thức đúng| a ll b |
|!|Trả về true nếu biểu thức sai|!a|

![](https://hackmd.io/_uploads/By7hTizla.png)

### Toán tử Bit
Toán tử Bitwise thực hiện các phép toán trên dạng nhị phân.


| Toán tử | Mô tả | 
| -------- | -------- | 
| &    | phép AND  |
| l |phép OR|
|^ |phép XOR|
|~ | phép NOT|
|<<|dịch bit sang trái|
|>>|dịch bit sang phải|

### Toán tử ba ngôi

![](https://hackmd.io/_uploads/HkqOz58g6.png)

*Cú pháp*
```javascript
variable_name = (condition) ? value1 : value2
```

```javascript
let food = {
    name: 'milk',
    cost: 10
}

let result = food.cost > 0 ? `${food.cost}$` : 'free';
console.log(result);
```
![](https://hackmd.io/_uploads/rJszf5Llp.png)


### Toán tử typeof
Để xác định kiểu dữ liệu của một biến, ta có thể sử dụng toán tử `typeof`. 

![](https://hackmd.io/_uploads/SJ4o-Afla.png)

### Các toán tử khác
![](https://hackmd.io/_uploads/HygmknzeT.png)


## Chuỗi
- Chuỗi ký tự là một kiểu dữ liệu căn bản được sử dụng để làm việc với các văn bản.
- Trong Javascript, các chuỗi được bao quanh bởi dấu nháy gồm:
   - Dấu ngoặc đơn
   - Dấu ngoặc kép
   - Dấu huyền
- Ví dụ:
```javascript
let a = 'Lập trình';
let b = "Javascript";
let result = `${a} ${b} cơ bản`;
```
### Các phương thức của chuỗi ký tự
![](https://hackmd.io/_uploads/HyHmr7HeT.png)

- Ví dụ:

```javascript=
//length: đo độ dài một chuỗi
let myString = 'Hoc JS co ban';
console.log(myString.length);

//Find index
console.log(myString.indexOf('JS'));
//nếu có nhiều ký tự giống nhau ta có làm như sau
let myString1 = 'Hoc JS co ban JS JS';
console.log(myString1.indexOf('JS', 6));
console.log(myString1.lastIndexOf('JS')); // tìm chuỗi cuối

//cut string
console.log(myString.slice(4, 6));

//Replace
console.log(myString.replace('JS', 'Javascript'));
console.log(myString1.replace(/JS/g, 'Javascript'));

// Trim: loại bỏ khoảng trắng thừa

//get a character by index
console.log(myString.charAt(2));
console.log(myString[2]);
```
![](https://hackmd.io/_uploads/Bk_05XrgT.png)

### Ký tự thoát
Ta có thể sử dụng ký tự thoát dấu gạch chéo ngược \ để thêm các ký tự đặc biệt trong một chuỗi.
![](https://hackmd.io/_uploads/HklmmdSgp.png)
## Đối tượng date
```javascript
let date = new Date();
console.log(date);

let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();

console.log(`${day}/${month}/${year}`);
```
![](https://hackmd.io/_uploads/SJN-sYIl6.png)

Hiển thị thêm giờ:
![](https://hackmd.io/_uploads/HJSuitUla.png)


## Hàm
### Khai báo hàm
*Cú pháp*
```javascript
function tên_hàm() {
    // Đoạn mã 
}
```
- Một hàm được khai báo bằng từ khóa `function`.
- Các quy tắc cơ bản của việc đặt tên một hàm tương tự như đặt tên cho một biến. Nên đặt tên mô tả cho hàm của mình. 
- Phần thân của hàm được viết trong dấu ngoặc nhọn {}.

### Gọi hàm
Để sử dụng, chúng ta cần thực hiện gọi hàm đó. 
Ví dụ:
```javascript
function nameOfFile () {
    console.log('Xin chào các bạn!');
}
nameOfFile();
```
![](https://hackmd.io/_uploads/HkgzQvrg6.png)

### Tham số trong hàm
Một hàm cũng có thể được khai báo với các tham số. Tham số là một giá trị được truyền khi khai báo một hàm.

```javascript
function nameOfFile (name) { //tham số
    console.log('Xin chào bạn ' + name + '!');
}
nameOfFile('Mary'); //truyền đối số

```
![](https://hackmd.io/_uploads/B1vn4DHea.png)

Ta có thể viết một hàm và sau đó gọi nó nhiều lần với các đối số khác nhau.

### `arguments`
```javascript
function nameOfFile () { 
    console.log(arguments);
}
nameOfFile('Mary', 'Bob'); 

```
![](https://hackmd.io/_uploads/HyN1PPrg6.png)


### Hàm trả về `return`
Câu lệnh `return` có thể được sử dụng để trả về giá trị cho một hàm. Câu lệnh `return` cũng đồng thời biểu thị rằng hàm đã kết thúc. Bất kỳ đoạn mã nào sau câu lệnh `return` sẽ không được thực thi. Nếu không có giá trị nào được trả về, hàm trả về một giá trị không xác định.

```javascript
function cong(a, b) {
    return a + b;
}

console.log(cong(4, 6));
```
![](https://hackmd.io/_uploads/Hyic5DHx6.png)
### Biểu thức hàm
Có dạng
```javascript
var ten_bien = function() {
    //đoạn mã
}
```

## Mảng 
Mảng là một đối tượng có thể lưu trữ nhiều phần tử.
### Mảng một chiều
#### Tạo mảng
- Sử dụng ký tự mảng []
```javascript
let name = ['Ben', 'Bob', 'Jenny'];
let num = [1, 2, 3, 4. 5];
```
- Sử dụng từ khóa `new`
```javascript
let name = new Array('Ben', 'Bob');
```
#### Truy cập vào phần tử của mảng
Note: Chỉ số của mảng bắt đầu bằng giá trị là số 0.

![](https://hackmd.io/_uploads/r1-d3KVea.png)

#### Thêm một phần tử vào mảng
- Dùng `push()` thêm phần tử vào cuối mảng và trả về độ dài của mảng mới
![](https://hackmd.io/_uploads/S1RQpFElp.png)

- Dùng `unshift()` thêm một phần tử mới vào đầu mảng và trả về độ dài mới của mảng.
![](https://hackmd.io/_uploads/BJzFTt4ep.png)

#### Thay đổi các phần tử của mảng
Ta cũng có thể thêm phần tử hoặc thay đổi phần tử bằng cách truy cập giá trị chỉ số.

![](https://hackmd.io/_uploads/H1RV0KNep.png)

#### Xóa một phần tử khỏi mảng
- Dùng `pop()` để xóa phần tử cuối cùng của mảng.
![](https://hackmd.io/_uploads/S1ZK19Vxa.png)

- Dùng `shift()` để xóa phần tử đầu tiên 
![](https://hackmd.io/_uploads/S1aWg5VeT.png)

#### Tìm độ dài mảng
Dùng thuộc tính `length` để tìm độ dài (số phần tử trong mảng).
![](https://hackmd.io/_uploads/Sk9De5Vl6.png)
#### Một số phương thức khác trong mảng
![](https://hackmd.io/_uploads/SJx0e9NlT.png)

#### `reduce()` method
`reduce()` có thể hiểu là phương thức trả về tổng của tất cả các thành phần trong một mảng.

*Cú pháp*
```javascript
reduce(callbackFn)
reduce(callbackFn, initialValue)

```
- `callbackFn`: là hàm thực thi cho từng phần tử trong mảng. Giá trị trả về của nó trở thành giá trị của tham số `accumulator` trong lần gọi tiếp theo của `callbackFn`. Đối với lệnh gọi cuối cùng, giá trị trả về sẽ trở thành giá trị của `reduce()`. Hàm được gọi với các đối số:
    - `accumulator`: là giá trị thu được từ lệnh gọi trước tới `callbackFn`(biến lưu trữ)
    - `currentValue`: giá trị của phần tử hiện tại.
    - `currentIndex`: vị trí của `currentValue` trong mảng. 
    - `array`: mảng đã được gọi.
- `initialValue` :giá trị khởi tạo
- `TypeError`: nếu mảng không có phần tử nào và `initialValue` không được cung cấp
Ví dụ:
```javascript
let product = [
    {
        id: 1,
        name: 'milk',
        cost: 10
    },
    {
        id: 2,
        name: 'egg',
        cost: 20
    },
    {
        id: 3,
        name: 'meat',
        cost: 50
    },
    {
        id: 4,
        name: 'vegetable',
        cost: 5
    },
];
let i = 0;
function costHandle(accumulator, currentValue, currentIndex, array){
    i++;
    let total = accumulator + currentValue.cost;
    console.table({
        'Lượt bán ': i,
        'Giá trị tích lũy ': accumulator,
        'Giá sản phẩm ': currentValue.cost,
        'Tổng' : total

    });
    return total;
}
let totalCost = product.reduce(costHandle, 0);
// đối số thứ nhất là function
// đối số thứ nhất là initialValue (giá trị khởi tạo)
console.log(totalCost);
```
Kết quả
![](https://hackmd.io/_uploads/rkZe2Wwlp.png)

Ví dụ 2:
```javascript
// Flat - "làm phẳng"
var depthArray = [1, 2, 3, [4, 5], 6, 7, [8, 9]]

var flatArray = depthArray.reduce(function(flatElements, depthElements){
    return flatElements.concat(depthElements);
// concat(): nối mảng
}, []);
console.log(flatArray);
```
![](https://hackmd.io/_uploads/ry3eHzDxT.png)



### Mảng hai chiều
 
```javascript=
let num = [[0, 2, 4, 6], [1, 3, 5, 7]];
```


## Cấu trúc rẽ nhánh
### Câu lệnh `if`
*Cú pháp:*
```javascript=
if (dieu_kien){
    //đoạn mã
}
```
- Câu lệnh if sẽ có nhiệm vụ kiểm tra biểu thức bên trong dấu ngoặc đơn ().

     - Nếu điều kiện là true, đoạn mã bên trong phần thân của if được thực thi.
     - Nếu điều kiện  là false, đoạn mã bên trong phần thân của if sẽ bị bỏ qua.
- Đoạn mã bên trong dấu ngoặc nhọn {} là phần nội dung của câu lệnh if.
Ví dụ:
```javascript=
var GPA = 3.4;
if (GPA > 3.2){
    console.log('Sinh viên giỏi');
}
```
![](https://hackmd.io/_uploads/Hy95GfQlp.png)
#### Câu lệnh `if...else`
*Cú pháp:*
```javascript
if (điều kiện) {
  // Đoạn mã 1
} else {
  // Đoạn mã 2
}
```
- Câu lệnh if..else kiểm tra điều kiện bên trong dấu ngoặc đơn ().
    - Nếu điều kiện là true,
         - Đoạn mã bên trong phần thân của if được thực thi.
         - Đoạn mã bên trong phần thân của else bị bỏ qua.
    - Nếu điều kiện là false,
        - Đoạn mã bên trong phần thân của else được thực thi.
        - Đoạn mã bên trong phần thân của if bị bỏ qua.

Ví dụ:
```javascript=
var GPA = 3.1;
if (GPA > 3.2){
    console.log('Sinh viên giỏi');
}
else{
    console.log('Sinh viên chưa đủ điều kiện đạt giỏi')
}
```
![](https://hackmd.io/_uploads/B1frNfQea.png)

####  Câu lệnh `if…else if`

*Cú pháp:*
```javascript
if (Điều kiện 1) {
  // Đoạn mã 1
} else if (Điều kiện 2) {
  // Đoạn mã 2
} else {
  // Đoạn mã 3
}
```
Ví dụ:
```javascript=
var GPA = 3.5;
if (GPA >= 3.6){
    console.log('Sinh viên xuất sắc');
}
else if (3.2 <= GPA < 3.6){
    console.log('Sinh viên giỏi');
}
else if (2.5 <= GPA < 3.2){
    console.log('Sinh viên khá');
}
else{
    console.log('Sinh viên trung bình');
}
```
![](https://hackmd.io/_uploads/rkfxIfmx6.png)

### Câu lệnh Switch
Câu lệnh switch sẽ có nhiệm vụ thực hiện việc đánh giá một biểu thức và thực thi phần nội dung của trường hợp mà đáp ứng và phù hợp với điều kiện của biểu thức.

*Cú pháp*
```javascript
switch(biểu thức) {
    case giá trị 1: 
        // Đoạn mã 1
        break;
    case giá trị 1: 
        // Đoạn mã 2
        break;
    case giá trị N:
        // Đoạn mã N
        break;

    default:
        // Đoạn mã của trường hợp mặc định
}
```

- Ví dụ:

```javascript
let date = 4 ;
switch (date) {
    case 2:
        console.log('Hôm nay là thứ 2');
        break;
    case 3:
        console.log('Hôm nay là thứ 3');
        break;
    default:
        crossOriginIsolated.log('Không biết!');
}
```
![](https://hackmd.io/_uploads/r1g-gcUeT.png)

**Lưu ý:** Nếu gặp câu lệnh break, câu lệnh switch sẽ kết thúc. Nếu câu lệnh break không được sử dụng, các trường hợp sau trường hợp trùng khớp sẽ được thực hiện lần lượt.

![](https://hackmd.io/_uploads/HknK79Lep.png)


## Vòng lặp (loop)
### Vòng lặp `for`
Cú pháp
```javascript
for (Khởi tạo; điều kiện; biểu thức cập nhật) {
     // nội dung vòng lặp for
}
```
Ví dụ
```javascript
for (var i = 1; i <= 10; i++) {
    console.log(i);
}
```
![](https://hackmd.io/_uploads/SyeYBcLxT.png)

```javascript
let languages = ['JS', 'PHP', 'Java', 'Python'];

let arrayLength = languages.length;

for(var i = 0; i < arrayLength; i++){
    console.log(languages[i]);
}
```
![](https://hackmd.io/_uploads/BkpHuc8e6.png)

#### `for ... in`
- Vòng lặp `for...in` trong JavaScript cho phép lặp qua tất cả các khóa (`key`) thuộc tính của một đối tượng.
*Cú pháp*
```javascript
for (khóa trong đối tượng) {
    // Đoạn mã
}
```
- Trong mỗi lần lặp của vòng lặp, một khóa được gán cho một biến. Vòng lặp tiếp tục cho tất cả các thuộc tính của đối tượng.
- Ví dụ: 
```javascript=
let student = {
    Name: 'Bob',
    Class: 12,
    ID: 1002
}
for(let key in student){    //duyệt qua student 
    console.log(`${key}: ${student[key]}`);
}
```
![](https://hackmd.io/_uploads/SyGv_c4xT.png)

#### `for...of`
- Vòng lặp for..of cho phép ta duyệt qua các đối tượng có kiểu dữ liệu như mảng, Set, Map, chuỗi ký tự,…

*Cú pháp:*
```javascript
for (Phần tử of Tập hợp) {
    // Đoạn mã
}
```
Ví dụ 1:

```javascript
var a = 'JavaScript';
for (var value of a){
    console.log(value)
}
```
Kết quả
```javascript=
J
a
v
a
S
c
r
i
p
t
```
Ví dụ 2:

```javascript=
let myInfo = {
    name: 'Quynh Anh',
    age: 19
};

for(var value of Object.keys(myInfo)){
    console.log(myInfo[value]);
}
//or
for(var value of Object.values(myInfo)){
    console.log(value);
}
//or
console.log(Object.values(myInfo));
//or
console.log(Object.keys(myInfo));
```
Kết quả

![](https://hackmd.io/_uploads/BkwDC5UxT.png)

#### So sánh `for...in` và `for...of`


| `for...in` |`for...of` | 
| -------- | -------- | 
| Được sử dụng để duyệt qua các khóa (`key`) của đối tượng.    | Được sử dụng để duyệt qua các giá trị (`value`) của các đối tượng có thể được duyệt qua.     | 
|Có thể được sử dụng để duyệt qua một đối tượng |Không được sử dụng để duyệt qua một đối tượng.|

### Vòng lặp `while` và `do...while`
#### Vòng lặp `while`
*Cú pháp*
```javascript
while (điều kiện) {
     // Đoạn mã
}
```
- Vòng lặp while sẽ thực hiện đánh giá điều kiện bên trong dấu ngoặc đơn ().
- Nếu điều kiện là true (đúng), đoạn mã bên trong vòng lặp while được thực thi. Điều kiện được kiểm tra lại sau mỗi lần lặp.
- Quá trình này tiếp tục cho đến khi điều kiện là false (sai). Khi điều kiện là false (sai), vòng lặp sẽ dừng lại.

Ví dụ:
```javascript
let languages = ['JS', 'PHP', 'Python', 'Java'];

var i = 0;
while(i < languages.length){
    console.log(languages[i]);
    i++;
}
```
![](https://hackmd.io/_uploads/BJ-zfsIg6.png)

#### Vòng lặp `do...while`
*Cú pháp:*

```javascript
do {
    // Đoạn mã
} while(Điều kiện)
```
- Phần thân của vòng lặp được thực thi lần đầu. Sau đó, điều kiện được kiểm tra ở lần lặp thứ 2.
- Nếu điều kiện là true (đúng), phần thân bên trong của vòng lặp được thực thi lại. Điều kiện được kiểm tra lại một lần nữa.
- Nếu điều kiện là false (sai), vòng lặp sẽ ngừng thực thi. Quá trình này tiếp tục cho đến khi điều kiện là false (sai). Lúc đó, vòng lặp sẽ dừng lại.


Ví dụ:
```javascript
let i = 0;
let isSuccess = false;
do {
    i++;
    console.log('Nhập lần ' + i);
    //thành công
    if (false) {
        isSuccess = true;

    }
} while (!isSuccess && i < 5)
```
Kết quả:
![](https://hackmd.io/_uploads/Hk5jvjLg6.png)

### `break`
Câu lệnh `break` trong JavaScript được sử dụng để dừng vòng lặp ngay lập tức và chuyển đến câu lệnh tiếp theo.
```javascript
for (var i = 0; i < 10; i++){
    console.log(i);
    if (i >= 3){
        break;
    }
}
```
![](https://hackmd.io/_uploads/HyLdx68xp.png)

### `continue`

Câu lệnh continue được sử dụng để bỏ qua lần lặp hiện tại của vòng lặp và luồng điều khiển của chương trình sẽ được chuyển sang lần lặp tiếp theo.
```javascript
for (var i = 0; i < 10; i++){
    if (i%2 == 0){
        continue;
    }
    console.log(i);
}
```

![](https://hackmd.io/_uploads/B1MQbpIlT.png)

## Đệ quy
Đệ quy là một quá trình mà trong đó một đối tượng sẽ tự thực hiện lời gọi chính nó. Một hàm tự gọi chính nó được gọi là một hàm đệ quy.

Cú pháp:
```javascript
function tên_hàm() {
   tên_hàm();
}
tên_hàm();
```


# HTML DOM
Khi một trang web được tải, trình duyệt sẽ tạo một mô hình DOM (Document Object Model)

![](https://hackmd.io/_uploads/BkBB9MvlT.png)

- Có 3 thành phần chính:
    - Element
    - Attribute
    - Text
## Document
Đại diện cho toàn bộ website
![](https://hackmd.io/_uploads/By-QzXwea.png)

```javascript
document.write();
```
## element
### Tìm thẻ HTLM thông qua ID
*Cú pháp*
```javascript
document.getElementById('idName');
```
Trong đó `idName` là id của thẻ HTML cần truy xuất tới.
Ví dụ:
```javascript
var headingNode = document.getElementById('heading');
console.log({
    element: headingNode
});
```
![](https://hackmd.io/_uploads/BJYX53wl6.png)
### Tìm thẻ HTLM thông qua class
*Cú pháp*
```javascript
document.getElementsByClassName('className');
```
Trong đó `className` là tên class của thẻ HTML muốn tìm.
Ví dụ:
```javascript
var headingNode = document.getElementsByClassName('heading');
console.log(headingNode);
```
![](https://hackmd.io/_uploads/SyzjhnvxT.png)

### Tìm thẻ HTLM thông qua tag
*Cú pháp*
```javascript
document.getElementsByTagName('tagName');
```
Ví dụ:
```javascript
var headingNode = document.getElementsByTagName('h1');
console.log(headingNode);
```
![](https://hackmd.io/_uploads/SyzjhnvxT.png)

### CSS selector
#### querySelector
```javascript
var headingNode = document.querySelector('.heading-2');
console.log(headingNode);
```
![](https://hackmd.io/_uploads/H1LzG-dxa.png)
#### querySelectorAll
```javascript
var headingNode = document.querySelectorAll('.box .heading-2');
console.log(headingNode);
```
![](https://hackmd.io/_uploads/BkRCz-Oep.png)
## attribute
Sử dụng hàm `setAttribute('tên attribute', 'giá trị attribute')` để thêm attribute.

## InnerText và textContent
Lấy ra dung text của element text
## innerHTML và outerHTML
Thêm element vào element


# CRUD bằng `fetch()`

## Tạo db.json
```json
{
  "student": [
    {
      "id": 1,
      "name": "Toán A1"
    },
    {
      "id": 2,
      "name": "Toán A2"
    },
    {
      "id": 3,
      "name": "Toán A3"
      
    }
  ]
}
```
Ta được http://localhost:3000/student
## Hiển thị trong HTML
```htmlmixed
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Fetch</title>
</head>

<body>

  <div>
    <h2>Danh sách môn học</h2>
    <ul id="list-subject">


    </ul>

  </div>
  <div>
    <div>
      <label><b>Tên</b></label>
      <input type="text" name="name">
    </div>
    <br>
    <div>
      <button id="create">Tạo</button>
    </div>
  </div>
<script src="./main.js"></script>
</body>
</html>
```
## Thực hiện trong JS
```javascript
let listSubjectBlock = document.querySelector('#list-subject')
let subjectAPI = 'http://localhost:3000/student';

function start() {
    getSubject(renderSubject);
    handleForm();
}
start();


function getSubject(callback) {
    fetch(subjectAPI)
        .then(function (respond) {
            return respond.json();
        })
        .then(callback);

}

//read
function renderSubject(subject) {
    let listSubjectBlock = document.querySelector('#list-subject')
    let html = subject.map(function (sub) {
        return `
    <li>
    <h4>${sub.name}</h4>
    <button onclick="deleteSubject(${sub.id})">Xóa</button> 
    <!-- thêm nút xóa -->
    <button onclick="handleUpdateSubject(${sub.id})">Sửa</button>
    </li>
    `;
    });

    listSubjectBlock.innerHTML = html.join('');

}
function handleForm() {
    let createButton = document.querySelector('#create');
    createButton.onclick = function () {
        let name = document.querySelector('input[name="name"]').value;
        console.log(name);
        let formData = {
            name: name,
        };
        createSubject(formData, function () {
            getSubject(renderSubject);
        });
    }
}
//create
function createSubject(data, callback) {
    let options = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
    }
    fetch(subjectAPI, options)
        .then(function (respond) {
            respond.json();
        }
        )
        .then(callback);
}

//delete
function deleteSubject(id) {
    let options = {
        method: 'DELETE',
        headers: {
            'Content-Type': 'application/json'
        },
    }
    fetch(subjectAPI + '/' + id, options)
        .then(function (respond) {
            respond.json();
        }
        )
        .then(callback);
}

//update
function updateSubject(id, data, callback) {
    let options = {
        method: 'PATCH',
        headers: {
            'Content-Type': 'application/json'
        },

        body: JSON.stringify(data)

    }

    fetch(subjectAPI + '/' + id, options)
        .then(function (respond) {
            respond.json();
        })
        .then(callback);
}

function handleUpdateSubject(id) {
    let name = document.querySelector('.name' + id);
    let editButton = document.querySelector('#create');
    
    let nameInput = document.querySelector('input[name="name"]');
    if (name) {
        nameInput.value = name.innerText;   
        editButton.innerText = "Save";
    }
    editButton.onclick = function () {
        var formData = {
            name: nameInput.value
        }
       updateSubject(id, formData, function () {
            getSubject(renderSubject);
        })

        // sửa xong thì trả về lại tạo form
        editButton.innerText = "Create";
        nameInput.value = '';
        handleForm();
    }

}
```
Kết quả:
![](https://hackmd.io/_uploads/rkwQfQngp.png)

Thêm
![](https://hackmd.io/_uploads/SJk2rQ2xa.png)

Sửa
![](https://hackmd.io/_uploads/r13V87nxa.png)

Xóa
![](https://hackmd.io/_uploads/SyvuLm3g6.png)



