JavaScript Scope and Closures

Scope và Closure là những khái niệm rất quan trọng trong Javascript và chúng cũng là hai khái niệm dễ khiến nhiều lập trình viên nhầm lẫn khi mới làm quen. Vì thế bài viết này với mục đích đưa ra cái nhìn rõ ràng hơn để giúp bạn có thể phân biệt đúng scope and closure.

Đầu tiên, ta sẽ tìm hiểu về scope.

Scope là gì ?

Scope trong Javascipts để xác định phạm vị của biến mà chúng ta có quyền truy cập . Có 2 loại scope đó là: global scope và local scope

Global scope

Nếu một biến được khai báo bên ngoài tất cả các hàm hoặc dấu ngoặc nhọn ({}), thì nó được xác định là được định nghĩa trong phạm vi toàn cục.

const globalVariable = 'some value'

Khi bạn đã khai báo một biến toàn cục, bạn có thể sử dụng biến đó ở bất cứ đâu trong mã của mình, ngay cả trong các hàm.

const hello = 'Hello CSS-Tricks Reader!'

function sayHello () {
  console.log(hello)
}

console.log(hello) // 'Hello CSS-Tricks Reader!'
sayHello() // 'Hello CSS-Tricks Reader!'

Mặc dù bạn có thể khai báo các biến trong phạm vi toàn cầu, nhưng không nên. Điều này là do có một cơ hội đặt tên xung đột, trong đó hai hoặc nhiều biến được đặt tên giống nhau. Nếu bạn đã khai báo các biến của mình bằng const hoặc let, bạn sẽ nhận được lỗi mỗi khi xảy ra xung đột tên. Điều này là không mong muốn.

// Don't do this!
let thing = 'something'
let thing = 'something else' // Error, thing has already been declared

Nếu bạn khai báo các biến của mình bằng var, biến thứ hai của bạn sẽ ghi đè lên biến đầu tiên sau khi nó được khai báo. Điều này cũng không mong muốn khi bạn làm cho mã của mình khó gỡ lỗi.

// Don't do this!
var thing = 'something'
var thing = 'something else' // perhaps somewhere totally different in your code
console.log(thing) // 'something else'

Local Scope

Các biến chỉ có thể sử dụng được trong một phần cụ thể của mã của bạn được coi là nằm trong phạm vi cục bộ. Các biến này cũng được gọi là biến cục bộ. Trong JavaScript, có hai loại local scope: function scope and block scope.

Function scope

Khi bạn khai báo một biến trong hàm, bạn chỉ có thể truy cập biến này trong hàm. Bạn không thể có được biến này một khi bạn thoát khỏi nó.

function sayHello () {
  const hello = 'Hello CSS-Tricks Reader!'
  console.log(hello)
}

sayHello() // 'Hello CSS-Tricks Reader!'
console.log(hello) // Error, hello is not defined

Block scope

Khi bạn khai báo một biến có const hoặc cho phép trong dấu ngoặc nhọn ({}), bạn chỉ có thể truy cập biến này trong dấu ngoặc nhọn đó. Trong ví dụ dưới đây, bạn có thể thấy lời chào được đặt trong phạm vi dấu ngoặc nhọn:

{
  const hello = 'Hello CSS-Tricks Reader!'
  console.log(hello) // 'Hello CSS-Tricks Reader!'
}

console.log(hello) // Error, hello is not defined

Function hoisting and scopes

Các hàm, khi được khai báo với một khai báo hàm, luôn luôn được kéo lên trên cùng của phạm vi hiện tại. Vì vậy, hai cái này là tương đương

// This is the same as the one below
sayHello()
function sayHello () {
  console.log('Hello CSS-Tricks Reader!')
}

// This is the same as the code above
function sayHello () {
  console.log('Hello CSS-Tricks Reader!')
}
sayHello()

Closures

Bất cứ khi nào bạn tạo một chức năng trong một chức năng khác, bạn đã tạo một closure. Các chức năng bên trong là closure . Việc closure thường được trả về để bạn có thể sử dụng các biến của hàm ngoài sau đó.

function outerFunction () {
  const outer = `I see the outer variable!`

  function innerFunction() {
    console.log(outer)
  }

  return innerFunction
}

outerFunction()() // I see the outer variable!

Vì hàm bên trong được trả về, bạn cũng có thể rút ngắn mã một chút bằng cách viết câu lệnh return trong khi khai báo hàm.

function outerFunction () {
  const outer = `I see the outer variable!`

  return function innerFunction() {
    console.log(outer)
  }
}

outerFunction()() // I see the outer variable!

Private variables with closures

Như bạn đã biết, các biến được tạo trong hàm không thể được truy cập bên ngoài hàm. Vì chúng không thể được truy cập, chúng còn được gọi là biến riêng. Tuy nhiên, đôi khi bạn cần truy cập vào một biến riêng tư như vậy. Bạn có thể làm như vậy với sự giúp đỡ của closures.

function secret (secretCode) {
  return {
    saySecretCode () {
      console.log(secretCode)
    }
  }
}

const theSecret = secret('CSS Tricks is amazing')
theSecret.saySecretCode()

Kết bài

Thông qua bài này mình hi vọng sẽ giúp các bạn phần nào hiển về biến trong Scope và Closures trong JavaScript .Trên đây là bài viết ngắn mình muốn giới thiệu cho mọi người về biến trong Scope và Closures trong JavaScript. Xin cảm ơn mọi người đã đọc bài viết.

Tài liệu tham khảo

https://css-tricks.com/javascript-scope-closures/