JavaScript - ES6: Hướng dẫn cho người mới bắt đầu về JavaScript hiện đại

Xin chào các pháp sư JavaScript tương lai! Tôi rất vui mừng được làm hướng dẫn viên của bạn trong hành trình thú vị vào thế giới ES6, bản cập nhật thay đổi cuộc chơi của JavaScript đã cách mạng hóa cách chúng ta viết mã. Với tư cách là người đã dạy lập trình hơn một thập kỷ, tôi không thể đợi được để chia sẻ phép màu của ES6 với các bạn. Nào, cầm lấy pháp杖 (hoặc bàn phím) của bạn, và chúng ta cùng nhảy vào!

JavaScript - ES6

Các tính năng mới trong ES6

ES6, còn được gọi là ECMAScript 2015, mang đến kho báu của các tính năng mới cho JavaScript. Nó giống như JavaScript đã đi học siêu nhân và trở về với một整套 sức mạnh mới! Hãy cùng khám phá những siêu năng lực này một lần nữa.

Hàm mũi tên (Arrow Functions)

Hàm mũi tên giống như những người anh em cool và hiện đại của hàm bình thường. Chúng ngắn hơn, gọn hơn và đôi khi còn mạnh mẽ hơn. Hãy xem một ví dụ:

// Cách cũ
function sayHello(name) {
return "Hello, " + name + "!";
}

// Hàm mũi tên
const sayHello = (name) => `Hello, ${name}!`;

console.log(sayHello("Alice")); // Output: Hello, Alice!

Trong ví dụ này, chúng ta đã chuyển đổi một hàm bình thường thành một hàm mũi tên. Chú ý rằng chúng ta đã loại bỏ từ khóa function và thêm dấu => (dấu mũi tên). Đó như thể hàm của chúng ta đã giảm cân và trông rất đẹp!

Phương pháp find() của mảng

Phương pháp find() giống như một thám tử cho các mảng của bạn. Nó duyệt qua mảng và trả về phần tử đầu tiên thỏa mãn điều kiện kiểm tra. Dưới đây là cách nó hoạt động:

const numbers = [1, 2, 3, 4, 5];
const firstEvenNumber = numbers.find(num => num % 2 === 0);

console.log(firstEvenNumber); // Output: 2

Trong trường hợp này, phương pháp find() của chúng ta đang tìm kiếm số nguyên tố đầu tiên. Nó kiểm tra từng số và khi tìm thấy số chia hết cho 2 mà không có phần dư, nó trả về số đó.

Phương pháp findIndex() của mảng

findIndex() là cousin của find(). Thay vì trả về phần tử, nó trả về chỉ số của phần tử đầu tiên thỏa mãn điều kiện kiểm tra. Hãy xem nó trong hành động:

const fruits = ["apple", "banana", "cherry", "date"];
const indexOfLongFruit = fruits.findIndex(fruit => fruit.length > 5);

console.log(indexOfLongFruit); // Output: 1

Tại đây, chúng ta đang tìm kiếm quả đầu tiên có hơn 5 chữ cái. "Banana" là quả đầu tiên thỏa mãn điều kiện này, vì vậy chỉ số của nó (1) được trả về.

Phương pháp from() của Array

Array.from() giống như một phù thủy có thể biến các đối tượng array-like hoặc iterable thành các mảng thực sự. Nó rất hữu ích khi làm việc với các phần tử DOM. Dưới đây là một ví dụ:

const name = "Alice";
const nameArray = Array.from(name);

console.log(nameArray); // Output: ["A", "l", "i", "c", "e"]

Trong trường hợp này, chúng ta đã chuyển đổi một chuỗi thành một mảng các ký tự riêng lẻ. Rất tuyệt vời, phải không?

Phương pháp keys() của Array

Phương pháp keys() trả về một đối tượng Array Iterator với các khóa của mảng. Nó giống như được cấp vé VIP để truy cập tất cả các chỉ số của mảng của bạn. Hãy xem cách nó hoạt động:

const fruits = ["apple", "banana", "cherry"];
const keys = fruits.keys();

for (let key of keys) {
console.log(key);
}
// Output:
// 0
// 1
// 2

Phương pháp này cho phép chúng ta truy cập các chỉ số của mảng, điều này có thể rất hữu ích trong một số tình huống.

Lớp (Classes)

Lớp trong ES6 đã mang lập trình hướng đối tượng đến JavaScript theo một cách tự nhiên hơn. Chúng giống như bản vẽ cho việc tạo đối tượng. Hãy tạo một lớp đơn giản:

class Dog {
constructor(name) {
this.name = name;
}

bark() {
return `${this.name} says woof!`;
}
}

const myDog = new Dog("Buddy");
console.log(myDog.bark()); // Output: Buddy says woof!

Trong ví dụ này, chúng ta đã tạo một lớp Dog với một constructor và một phương pháp. Chúng ta sau đó có thể tạo các đối tượng Dog mới bằng cách sử dụng lớp này.

Từ khóa const

Từ khóa const giống như một két an toàn cho các biến của bạn. Một khi bạn đặt giá trị vào, nó sẽ bị khóa và không thể thay đổi. Nó rất phù hợp cho các giá trị không nên được gán lại. Dưới đây là cách nó hoạt động:

const PI = 3.14159;
// PI = 3; // Điều này sẽ gây ra lỗi

console.log(PI); // Output: 3.14159

Trong ví dụ này, chúng ta đã宣布 PI là một hằng số. Nếu chúng ta cố gắng gán lại nó, JavaScript sẽ ném ra một lỗi.

Từ khóa let

let giống như anh em trách nhiệm hơn của var. Nó cung cấp block-scoping, điều này có thể giúp ngăn ngừa nhiều lỗi lập trình phổ biến. Dưới đây là một ví dụ:

let x = 1;

if (true) {
let x = 2; // Đây là một 'x' khác
console.log(x); // Output: 2
}

console.log(x); // Output: 1

Trong trường hợp này, x trong khối if là một biến khác so với x ngoài khối, thanks to let's block-scoping.

Tham số mặc định

Tham số mặc định giống như một lưới an toàn cho các hàm của bạn. Chúng cung cấp giá trị mặc định cho các tham số nếu không có đối số hoặc undefined được truyền. Hãy xem cách chúng hoạt động:

function greet(name = "Guest") {
return `Hello, ${name}!`;
}

console.log(greet()); // Output: Hello, Guest!
console.log(greet("Alice")); // Output: Hello, Alice!

Trong ví dụ này, nếu chúng ta không cung cấp một tên, hàm sử dụng "Guest" làm mặc định.

Vòng lặp for...of

Vòng lặp for...of là một cách mới, ngắn gọn hơn để duyệt qua các đối tượng iterable như mảng. Nó giống như một tour hướng dẫn qua dữ liệu của bạn. Dưới đây là cách nó hoạt động:

const fruits = ["apple", "banana", "cherry"];

for (let fruit of fruits) {
console.log(fruit);
}
// Output:
// apple
// banana
// cherry

Vòng lặp này tự động duyệt qua mỗi phần tử của mảng, làm cho mã của chúng ta sạch sẽ và dễ đọc hơn.

Tham số rest

Tham số rest giống như một lưới bắt tất cả các đối số thừa trong một hàm. Nó được biểu thị bằng ba dấu chấm (...) theo sau tên. Dưới đây là một ví dụ:

function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3, 4)); // Output: 10

Trong trường hợp này, ...numbers bắt tất cả các đối số và đặt chúng vào một mảng, sau đó chúng ta tính tổng chúng.

Mô-đun (Modules)

Mô-đun trong ES6 giống như các khối LEGO cho mã của bạn. Chúng cho phép bạn chia mã của bạn thành các tệp riêng biệt và nhập/xuất chức năng khi cần thiết. Dưới đây là một ví dụ đơn giản:

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

// main.js
import { add, subtract } from './math.js';

console.log(add(5, 3)); // Output: 8
console.log(subtract(5, 3)); // Output: 2

Phương pháp tiếp cận này giúp giữ mã của bạn tổ chức và có thể tái sử dụng.

Đối tượng Map

Đối tượng Map giống như các đối tượng siêu năng lực. Chúng cho phép các khóa của bất kỳ loại nào và duy trì thứ tự của các mục nhập. Dưới đây là cách chúng hoạt động:

const myMap = new Map();

myMap.set('name', 'Alice');
myMap.set(1, 'number one');

console.log(myMap.get('name')); // Output: Alice
console.log(myMap.get(1)); // Output: number one

Maps đặc biệt hữu ích khi bạn cần liên kết dữ liệu bổ sung với một đối tượng.

Các phương pháp toàn cục mới

ES6 đã giới thiệu một số phương pháp toàn cục mới. Hãy xem một trong số chúng: isFinite().

console.log(Number.isFinite(10)); // Output: true
console.log(Number.isFinite(Infinity)); // Output: false
console.log(Number.isFinite("10")); // Output: false

Phương pháp này kiểm tra xem một giá trị có phải là một số有限的 hay không, trả về true hoặc false.

Các phương pháp mới của Math

ES6 cũng mang lại các phương pháp mới của Math. Một trong số đó là Math.trunc(), loại bỏ phần thập phân của một số:

console.log(Math.trunc(4.9)); // Output: 4
console.log(Math.trunc(-4.2)); // Output: -4

Phương pháp này rất hữu ích khi bạn cần làm việc với các số nguyên.

Các phương pháp mới của Number

Các phương pháp mới của Number cũng được giới thiệu. Hãy xem Number.isInteger():

console.log(Number.isInteger(10)); // Output: true
console.log(Number.isInteger(10.5)); // Output: false

Phương pháp này kiểm tra xem một giá trị có phải là một số nguyên hay không.

Các thuộc tính mới của Number

ES6 đã thêm các thuộc tính mới của Number. Dưới đây là một ví dụ với Number.EPSILON:

console.log(Number.EPSILON); // Output: 2.220446049250313e-16

EPSILON đại diện cho khoảng cách nhỏ nhất giữa hai số có thể biểu diễn.

Promises

Promises giống như các IOU trong JavaScript. Chúng đại diện cho một giá trị có thể không sẵn sàng ngay lập tức, nhưng sẽ có sẵn vào một thời điểm nào đó. Dưới đây là một ví dụ đơn giản:

const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Success!");
}, 1000);
});

myPromise.then(result => console.log(result)); // Output sau 1 giây: Success!

Promises rất quan trọng cho việc xử lý các hoạt động không đồng bộ trong JavaScript.

Đối tượng Set

Đối tượng Set là các bộ sưu tập các giá trị duy nhất. Chúng giống như các mảng, nhưng không có phần tử trùng lặp. Dưới đây là cách chúng hoạt động:

const mySet = new Set([1, 2, 3, 3, 4]);

console.log(mySet); // Output: Set(4) {1, 2, 3, 4}

Sets tự động loại bỏ các giá trị trùng lặp, điều này có thể rất hữu ích trong một số tình huống.

Các phương pháp mới của String

ES6 đã giới thiệu một số phương pháp mới của String. Hãy xem startsWith():

const str = "Hello, world!";

console.log(str.startsWith("Hello")); // Output: true
console.log(str.startsWith("world")); // Output: false

Phương pháp này kiểm tra xem một chuỗi có bắt đầu bằng các ký tự được chỉ định hay không.

Ký hiệu Symbol

Ký hiệu Symbol là một loại nguyên thủy mới trong ES6. Chúng duy nhất và không thể thay đổi, thường được sử dụng làm khóa thuộc tính. Dưới đây là một ví dụ:

const mySymbol = Symbol("mySymbol");
const obj = {
[mySymbol]: "Hello, Symbol!"
};

console.log(obj[mySymbol]); // Output: Hello, Symbol!

Ký hiệu được sử dụng để tạo các khóa thuộc tính không phải là chuỗi trong các đối tượng.

Toán tử spread

Toán tử spread (...) giống như một pháp杖 ma thuật có thể lan tỏa một đối tượng iterable thành các phần tử riêng lẻ. Nó rất linh hoạt. Dưới đây là một ví dụ:

const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];

console.log(arr2); // Output: [1, 2, 3, 4, 5]

Toán tử spread đã lan tỏa arr1 thành các phần tử riêng lẻ trong arr2.

Kết luận

Uf! Chúng ta đã bao quát rất nhiều nội dung, phải không? ES6 đã mang lại rất nhiều tính năng thú vị cho JavaScript, và chúng ta mới chỉ chạm vào bề mặt. Kết quả là, chìa khóa để thành thạo các khái niệm này là thực hành. Vậy, hãy ra ngoài và viết mã! Thử nghiệm với các tính năng mới này, làm vỡ, sửa chúng và vui chơi trong quá trình. Trước khi bạn biết điều gì, bạn sẽ viết JavaScript hiện đại như một chuyên gia!

Dưới đây là bảng tóm tắt tất cả các phương pháp chúng ta đã thảo luận:

Phương pháp Mô tả
Arrow Functions Cách viết ngắn hơn cho các biểu thức hàm
Array.find() Trả về giá trị của phần tử đầu tiên trong mảng thỏa mãn điều kiện kiểm tra
Array.findIndex() Trả về chỉ số của phần tử đầu tiên trong mảng thỏa mãn điều kiện kiểm tra
Array.from() Tạo một bản sao nông của một đối tượng array-like hoặc iterable
Array.keys() Trả về một Array Iterator chứa các khóa cho mỗi chỉ số trong mảng
Class Mẫu cho tạo đối tượng, cung cấp cú pháp sạch sẽ cho lập trình hướng đối tượng
const Khai báo một biến block-scoped, không thể thay đổi
let Khai báo một biến block-scoped, có thể thay đổi
Default Parameters Cho phép các tham số có giá trị mặc định nếu không có đối số hoặc undefined được truyền
for...of Tạo một vòng lặp duyệt qua các đối tượng iterable
Rest Parameter Cho phép một hàm nhận một số lượng không xác định các đối số dưới dạng một mảng
Modules Cho phép chia mã thành các tệp riêng biệt và nhập/xuất chức năng khi cần thiết
Map Bộ sưu tập các mục có khóa, cho phép các khóa của bất kỳ loại nào
Number.isFinite() Kiểm tra xem một giá trị có phải là một số有限的 hay không
Math.trunc() Loại bỏ phần thập phân của một số
Number.isInteger() Kiểm tra xem một giá trị có phải là một số nguyên hay không
Number.EPSILON Đại diện cho khoảng cách nhỏ nhất giữa hai số có thể biểu diễn
Promise Đại diện cho việc hoàn thành hoặc thất bại của một hoạt động không đồng bộ
Set Bộ sưu tập các giá trị duy nhất
String.startsWith() Kiểm tra xem một chuỗi có bắt đầu bằng các ký tự được chỉ định hay không
Symbol Loại nguyên thủy duy nhất và không thể thay đổi

Chúc các bạn lập trình vui vẻ, và may mắn với ES6!

Credits: Image by storyset