•   09.03.2026
Programming Javascript Lập Trình Viên Tập Sự

Kiến thức javascript thực chiến cần nắm phần 1

1. Scope, Closure

Scope là gì ?

Scope phạm vi truy cập của biến trong chương trình.

Các loại scope cơ bản:

  • Global scope: biến khai báo bên ngoài mọi hàm/ block

  • Function scope: biến trong hàm chỉ dùng trong hàm đó.

  • Block scope: biến khai báo bằng let, const chỉ dùng trong {}.

Ví dụ:

const globalVar = "blog chia se kien thuc ve cong nghe";

function testScope() {
    const functionVar = "day la function scope";
    if (true) {
        let blockVar = "day la block scope";
        console.log(globalVar);   // OK
        console.log(functionVar); // OK
        console.log(blockVar);    // OK
    }

  // console.log(blockVar); // Error
}

testScope();

Closure là gì?

Closure là một hàm ghi nhớ được biến ở scope bên ngoài của nó, kể cả khi scope bên ngoài đã thực thi xong.

Ví dụ:

function createCount() {
    let count = 0;

    return function() {
        count++;
        return count;
    }
}

const counter = createCount();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

Ở đây hàm trả về vẫn nhớ biến count.

So sánh Scope & Closure

  • Scope = quy tắc xác định biến nào truy cập được ở đâu

  • Clouse = hiện tượng hàm giữ lại biến từ scope bên ngoài

2. Hosting

Định nghĩa: Hoisting là cơ chế Javascript đưa phần khai báo lên đầu scope trước khi chạy code.

Với var:

  • được hoist

  • giá trị ban đầu là undefined

console.log(a); // undefined
var a = 10;

JS hiểu gần giống:

var a;
console.log(a);
a = 10;

Với letconst:

  • cũng được hoist

  • nhưng nằm trong Temporal Dead Zone (TDZ)

  • không dùng trước khi khai báo

// console.log(b); // ReferenceError
let b = 20;

Với function declaration:

sayHello(); // "Hello"

function sayHello() {
  console.log("Hello");
}

So sánh:

  • var: hoist và dùng trước được, nhưng là undefined

  • let / const: hoist nhưng không dùng trước được

  • function declaration: hoist đầy đủ

  • function expression: không như function declaration

3. this

Định nghĩa

thisđối tượng đang gọi hàm tại thời điểm hàm được thực thi.

Quan trọng: this không phụ thuộc nơi hàm được viết, mà phụ thuộc cách hàm được gọi.

Ví dụ cơ bản

  1. Gọi như method

const user = {
  name: "An",
  sayHi() {
    console.log(this.name);
  }
};

user.sayHi(); // "An"
  1. Gọi như function thường

function show() {
  console.log(this);
}

show();
  • Trong trình duyệt non-strict: có thể là window

  • Trong strict mode: undefined

  1. Arrow function

Arrow function không có this riêng, nó lấy this từ scope bên ngoài.

const obj = {
  name: "Tuan",
  normal() {
    console.log(this.name);
  },
  arrow: () => {
    console.log(this.name);
  }
};

obj.normal(); // "Tuan"
obj.arrow();  // thường không phải "Tuan"

So sánh function thường và arrow function

  • Function thường: this do cách gọi quyết định

  • Arrow function: this lấy từ bên ngoài, không bind lại được theo cách thông thường.

4. Prototype ở mức cơ bản

Định nghĩa

Javascript dùng prototype-based inheitance.

Mỗi object có thể liên kết tới một object khác gọi là prototype. Khi truy cập thuộc tính:

  • nếu object hiện tại không có

  • JS sẽ tìm lên prototype chain

Ví dụ:

const animal = {
    eats: true
};

const dog = Object.create(animal);
dog.barks = true;

console.log(dog.barks); // true
console.log(dog.eats);  // true (lấy từ prototype)

Với constructor function

function Persion(name) {
    this.name = name;
}

Perion.prototype.sayHi = function() {
    console.log("Hi, I am " + this.name)
}

const p1 = new Person("Tuan");
p1.sayHi(); // Hi, I am Tuan

So sánh

  • Thuộc tính đặt trong this : riêng cho từng object

  • Thuộc tính/method đặt trong prototype: dùng chung cho nhiều object

Ví dụ:

function User(name) {
  this.name = name; // riêng
}

User.prototype.sayHello = function () {
  console.log("Hello " + this.name); // dùng chung
};

5. Array methods: map, filter, reduce

map

Dùng để biến đổi từng phần tử và trả về mảng mới cùng số lượng phần tử.

// array map
const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);

console.log(doubled); // [2, 4, 6]

filter

Dùng để lọc phần tử theo điều kiện, trả về mảng mới.

const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(n => n % 2 === 0);

console.log(evens); // [2, 4]

reduce

Dùng để gom mảng thành một giá trị duy nhất.

const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, cur) => acc + cur, 0);

console.log(sum); // 10

So sánh

  • map: sửa đổi từng phần tử

  • filter: chọn phần tử thỏa điều kiện

  • reduce: gom về 1 kết quả

So sánh nhanh

const arr = [1, 2, 3, 4];

console.log(arr.map(x => x * 2));         // [2, 4, 6, 8]
console.log(arr.filter(x => x > 2));      // [3, 4]
console.log(arr.reduce((a, b) => a + b)); // 10

6. Destructuring, Spread/Rest

Destructuring

Là cách tách giá trị từ object hoặc array ra biến.

Array destructuring

const arr = [10, 20, 30];
const [a, b] = arr;

console.log(a); // 10
console.log(b); // 20

Object destructuring

const user = { name: "Minh", age: 25 };
const { name, age } = user;

console.log(name); // Minh
console.log(age); // 25

Spread

Spread dùng để trải phần tử / thuộc tính ra

// spread basic
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4];

console.log(arr2); // [1, 2, 3, 4];
// spread object
const user = { name: "An" };
const updateUser = { ...user, age: 20 };

console.log(updatedUser); // { name: "An", age: 20 }

Rest

Rest dùng để gom phần tử lại.

// rest basic
const [first, ...rest] = [1, 2, 3, 4];
console.log(first); // 1
console.log(rest); // [2, 3, 4]
// rest params
function sum(...numbers) {
    return numbers.reduce((a, b) => a + b, 0)
}

console.log(sum(1, 2, 3)); // 6

So sánh Spread và Rest

Cùng dùng cú pháp ... nhưng khác vai trò:

  • Spread = bung ra

  • Rest = gom lại

7. Module import/export

Định nghĩa

Module giúp chia code thành nhiều file để dễ quản lý, tái sử dụng.

Export

Named export

export const pi = 3.14

export function add(a, b) {
    return a + b;
}

Default export

export default function greet(name) {
    return `Hello, ${name}`;
}

Import

Import named

import { pi, add } from "./math.js";

console.log(pi);
console.log(add(2, 3));

Import default

import greet from "./greet.js";

console.log(greet("Lan"));

So sánh named export và default export

  • Named export: một file có thể export nhiều thứ

  • Default export: mỗi file chỉ có 1 default export

  • Named import phải đúng tên, default import thì đặt tên gì cũng được

8. Promise, async/await

Promise là gì?

Promise là object đại diện cho kết quả của tác vụ bất đồng bộ trong tương lai.

Ba trạng thái:

  • pending

  • fulfiled

  • rejected

Ví dụ

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

promise.then(result => {
  console.log(result);
});

async/await là gì?

async/await là cú pháp giúp viết code bất đồng bộ trông giống đồng bộ hơn.

function wait() {
  return new Promise(resolve => {
    setTimeout(() => resolve("Finished"), 1000);
  });
}

async function run() {
  const result = await wait();
  console.log(result);
}

run();

So sánh Promise và async/await

  • Promise + .then(): chain bằng callback

  • async/await: dễ đọc hơn trong nhiều trường hợp

  • await chỉ dùng bên trong async function (hoặc top-level await trong một số môi trường/module)

9. Event loop, microtask/macrotask

Định nghĩa ngắn gọn

JavaScript chạy theo cơ chế single-threaded nhưng xử lý bất đồng bộ nhờ:

  • Call stack

  • Web APIs / runtime APIs

  • Task queues

  • Event loop

Macrotask

Ví dụ:

  • setTimeout

  • setInterval

  • setImmediate (một số môi trường)

  • I/O, UI events

Microtask

Ví dụ:

  • Promise.then/catch/finally

  • queueMicrotask

  • MutationObserver

Quy tắc quan trọng

Sau khi call stack rỗng:

  1. chạy hết microtask queue

  2. rồi mới lấy 1 macrotask

  3. lặp lại

Ví dụ

console.log("1");

setTimeout(() => {
  console.log("2");
}, 0);

Promise.resolve().then(() => {
  console.log("3");
});

console.log("4");

kết quả

1
4
3
2

So sánh microtask và macrotask

  • Microtask ưu tiên cao hơn

  • Promise.then thường chạy trước setTimeout(..., 0)

10) fetch, error handling

fetch là gì ?

fetch dùng để gửi HTTP request trong JavaScript.

Ví dụ GET

fetch("https://jsonplaceholder.typicode.com/posts/1")
  .then(response => response.json())
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error("Error:", error);
  });

Dùng với async/await

async function getPost() {
  try {
    const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");

    if (!response.ok) {
      throw new Error("HTTP error: " + response.status);
    }

    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Fetch failed:", error.message);
  }
}

getPost();

Error handling

Trong JS, thường xử lý lỗi bằng:

  • .catch()

  • try...catch

  • tự throw new Error(...)

Lưu ý quan trọng với fetch

fetch() không tự reject chỉ vì status là 404 hay 500.
Nó chỉ reject khi có lỗi mạng, CORS, request bị chặn...

Vì vậy cần kiểm tra:

if (!response.ok) {
  throw new Error(`HTTP error: ${response.status}`);
}

So sánh

  • .catch() hợp với Promise chain

  • try...catch dễ đọc hơn khi dùng async/await

  • response.ok xử lý lỗi HTTP

  • catch xử lý lỗi runtime / network


Hashtags: