JavaScript là một trong những ngôn ngữ được nhiều nhà phát triển lựa chọn. Nếu bạn muốn trở thành một chuyên gia JavaScript và/hoặc đang chuẩn bị cho một cuộc phỏng vấn xin việc thì các khái niệm cơ bản của ngôn ngữ lập trình này bạn cần phải nắm.
Bài viết này không bao gồm tất cả những khái niệm có trong JavaScript, nhưng là những khái niệm cơ bản mà bạn cần biết.
1. IIFE
IIFE là viết tắt của Immediately Invoked Function Expression. Đây là hàm được gọi ngay sau khi được tạo.
Làm thế nào bạn có thể xác định một IIFE? Hãy xem ví dụ dưới đây:
Khi code được thực thi, tính năng console sẽ in ra Hello world ngay lập tức.
Lý do sử dụng IIFE là để bảo vệ khả năng truy cập của các biến. Các biến được định nghĩa trong IIFE không thể được truy cập từ bên ngoài. Đó là cách để viết code để dễ bảo trì và ngăn nguồn của bạn trở thành một mớ hỗn độn.
2. Cấu trúc MVC
Không chỉ trong JavaScript, mà cấu trúc cơ bản này được sử dụng trong hầu hết các ngôn ngữ lập trình. Khác với cái tên MVC, việc sắp xếp code của bạn thành các lớp khác nhau như data, view và logic và xử lý chúng một cách riêng biệt là một khái niệm phổ biến.
Khi một dự án trở nên ít hơn, bạn cần một cấu trúc để mở rộng quy mô mà không cần phải cắm đầu vào tường. MVC là một trong những công cụ tốt nhất để theo dõi ngay từ đầu cho kế hoạch dài hạn. Tại một số thời điểm trong tương lai khi thêm các tính năng mới hoặc điều tra lỗi, bạn sẽ cảm ơn bản thân đã dành thời gian triển khai MVC.
3. Closure
Chúng ta sử dụng khái niệm này khi nói về một hàm bên trong luôn có quyền truy cập vào các biến và tham số của hàm bên ngoài của nó, ngay cả sau khi hàm bên ngoài đã trả về.
Closure
cho phép bạn cung cấp khả năng truy cập vào dữ liệu bên trong một hàm mà không cần trực tiếp sửa đổi chúng. Bằng cách này, bạn có thể bảo vệ code của mình trong khi cung cấp cho người khác khả năng mở rộng code. Đặc biệt là khi bạn phát hành một thư viện.
const sayHelloTo = name => {
let message = ‘Hello ‘ + name;
return () => console.log(message);
}
const sayHelloToAmy = sayHelloTo(‘Amy’);
sayHelloToAmy(); // Hello Amy
4. Async / await
Async / await cho phép bạn làm việc với xử lý không đồng bộ (asynchronous). Bạn thường rơi vào các tác vụ không đồng bộ khi xử lý việc gọi API. Dữ liệu cần được tìm nạp đầy đủ trước khi hiển thị trên view.
Điểm mấu chốt của việc sử dụng async / await là bạn có loại bỏ callbacks. Code lồng nhau làm cho code của bạn trở nên xấu xí và ít khả năng bảo trì hơn.
Xem ví dụ bên dưới để biết cách sử dụng async / await:
const displayData = async () => {
const data = await fetch(‘https://api.github.com/repositories');
const jsonData = await data.json();
console.log(jsonData);
};
displayData();
5. Scope
Có hai loại scope (pham vi hoạt động) trong JavaScript: scope cục bộ và scope toàn cục. Bạn có thể tưởng tượng một phạm vi hoạt động thay đổi là một con bò được buộc vào cột bằng dây. Nó chỉ có thể di chuyển trong một khu vực giới hạn, tùy thuộc vào độ dài của sợi dây.
Với ẩn dụ đó, biến cục bộ giống như một con bò bị trói bởi một sợi dây ngắn và biến toàn cục giống như một con bò không có sợi dây nào cả.
Ví dụ:
// Global scope
const globalCow = ‘global cow’;
const showCow = () => {
const localCow = ‘local cow’;
return globalCow;
};
const clonedCow = globalCow;
const mixedCow = globalCow + localCow; // error: Uncaught ReferenceError: localCow is not defined
Như bạn có thể thấy, biến globalCow có thể được sử dụng ở bất kỳ đâu ngay cả trong ngữ cảnh cục bộ của hàm showCow. Nhưng bạn không thể sử dụng biến localCow bên ngoài hàm showCow vì nó được định nghĩa cục bộ.
6. Giá trị so với tham chiếu
Khi bạn chỉ định giá trị (value) cho các biến, việc chỉ định giá trị không đơn giản như vậy. Bạn cần hiểu liệu đó là giá trị thực hay tham chiếu (reference), nếu không, bạn có thể thay đổi các giá trị một cách không chủ ý.
Câu chuyện thật dễ dàng khi bạn gán các kiểu nguyên thủy như String
, Number
hoặc Boolean
. Chúng là giá trị thực.
Phức tạp hơn một chút nếu bạn gán các Object
, Array
hoặc Function
. Lần này, biến sẽ không giữ giá trị thực mà là tham chiếu đến giá trị thực trong bộ nhớ.
Ví dụ:
let num1 = 1;
let num2 = num1;
// Thay đổi giá trị của num2 không làm thay đổi giá trị của num1
num2 = 4;
console.log (num1); // 1
console.log (num2); // 4
let arr1 = [‘Amy’, ‘John’];
cho arr2 = arr1;
// Thay đổi giá trị của các phần tử trong arr2 dẫn đến việc thay đổi giá trị của các phần tử trong arr1
arr2 [0] = ‘Jane’;
console.log (arr1); // [“Jane”, “John”]
console.log (arr2); // [“Jane”, “John”]
7. Callback
Trong JavaScript, một hàm callback
là một hàm được thực thi sau khi một hàm khác được gọi. Bạn có thể chuyển một hàm callback
làm tham số cho các hàm khác.
Vậy tại sao chúng ta sử dụng callback
? Thông thường, đoạn code chúng ta viết chạy tuần tự từ trên xuống dưới. Tuy nhiên, trong một số trường hợp, có những công việc cần được thực hiện trước khi thực hiện những công việc khác. Đây là lúc callback
có ích.
const fetchUsers = callback => {
setTimeout(() => {
let response = ‘[{name: “Amy”}, {name: “John”}]’;
callback(response);
}, 500);
};
const showUsers = users => console.log(users);
fetchUsers(showUsers);
Trong ví dụ trên, chúng ta gọi hàm fetchUsers và chuyển hàm callback showUsers làm tham số. Khi tất cả dữ liệu được tải đầy đủ, showUsers sẽ hiển thị trên màn hình.
8. Prototype
Bất cứ khi nào chúng ta tạo một hàm hoặc đối tượng trong JavaScript, một thuộc tính nguyên mẫu (prototype) sẽ được thêm vào bên trong chúng. Nguyên mẫu là một đối tượng được liên kết với các chức năng và đối tượng theo mặc định, trong đó chúng ta có thể đính kèm các thuộc tính bổ sung có thể được kế thừa bởi các đối tượng khác.
Ví dụ:
function Person() {
this.name = ‘Amy’;
this.age = 28;
}
Person.prototype.job = ‘Programmer’;
Person.prototype.showName = function() {
console.log(‘My name is ‘ + this.name);
}
let person = new Person();
person.showName(); // My name is Amy
9. Class
Trước ES6, không có class nào trong JavaScript. Bạn chỉ có thể tiếp cận khái niệm tương tự class theo cách của hàm.
function Book(title) {
this.title = title;
}
Book.prototype.showTitle = function() {
console.log(this.title);
};
let book = new Book(‘JavaScript’);
book.showTitle(); // JavaScript
Trong ES6, bạn có thể tạo một class thực tế giống như bất kỳ nền tảng ngôn ngữ dựa trên class nào:
class Book {
constructor(title) {
this.title = title;
}
showBook() {
console.log(this.title);
}
}
let book = new Book(‘ES6’);
book.showBook();
Thật tiện lợi vì nó hợp nhất một số cách tạo các class thành một class duy nhất.
10.Destructuring
Đó là một cách dễ dàng để trích xuất các thuộc tính từ các đối tượng.
Cách sử dụng cơ bản:
const person = {
name: ‘Amy’,
age: 28
};
let { name, age } = person;
console.log(name); // Amy
console.log(age); // 28
Bạn có thể giữ các biến giống như tên thuộc tính như trên hoặc xác định các biến mới:
let { name: newName, age: newAge } = person;
console.log(newName); // Amy
console.log(newAge); // 28
11. Xử lý Spread Operator
Spread Operator cung cấp cho bạn quyền truy cập vào bên trong của một đối tượng có thể lặp lại. Nói một cách đơn giản, đó là một cách nhanh chóng và ngắn gọn để thêm các mục vào mảng, kết hợp các đối tượng hoặc kéo các mục riêng lẻ ra khỏi một mảng rồi chuyển chúng vào một hàm.
// Combining Arrays
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let arr3 = […arr1, …arr2];
console.log(arr3); // [1, 2, 3, 4, 5, 6]
// Combining Objects
let obj1 = {
name: ‘Amy’,
age: 28
};
let obj2 = {
job: ‘programmer’
};
let obj3 = { …obj1, …obj2 };
console.log(obj3); // {name: “Amy”, age: 28, job: “programmer”}
// Spreading out an array and pass it to a function
const sum = (…arr) => {
const length = arr.length;
let sum = 0;
for (let i = 0; i < length; i++) {
sum += arr[i];
}
return sum;
};
let arr = [3, 5, 3, 2, 1];
console.log(sum(…arr)); // 14
console.log(sum(3, 5, 4, 1)); // 13
Kết luận
Bạn có hiểu đầy đủ tất cả các khái niệm JavaScript cơ bản trên không? Nếu không, đã đến lúc kiểm tra lại để củng cố kiến thức của mình và nâng các kỹ năng của bạn lên cấp độ tiếp theo.
Bạn có những khái niệm nào cần bổ sung? Hãy để lại bình luận bên dưới nhé.
Bài của Amy J. Andrews đăng trên javascript.plainenglish.io