Có hai loại scope (phạm vi) chính của biến trong JavaScript, là global và local. Ngoài ra còn có phạm vi window.
Global Scope
Là phạm vi toàn cục, biến có phạm vi này có thể được truy cập từ bất cứ đâu trong file code.
Vòng đời của biến global chỉ kết thúc khi chương trình bị thoát. Điều này đồng nghĩa với việc khi chúng ta refresh hay tắt trang web, vùng nhớ của biến global sẽ bị mất.
Function Scope
Khi một hàm (function) được gọi thực thi, một phạm vi mới sẽ được tạo ra, có tên là function scope. Đoạn code dưới đây có hai loại phạm vi: global và function.
var a = 10 // global scope
function f() {
// inside function scope
} // global scope
f() // function scope was created
Hàm sẽ có global scope hoặc function scope tùy vào vị trí khai báo. Ví dụ:
{
function f() {} // global scope
}
function g() {
function f() {} // function scope
}
Các hàm có thể truy cập đến các biến nằm bên ngoài phạm vi của nó:
var b = 2 // global scope
function mod(a) {
// inside function scope
return a % b
}
console.log(mod(7)) // 1
console.log(mod(10)) // 0
Nếu một biến a
được khai báo bên trong hàm f
và được tham chiếu bởi một hàm g
khác cũng bên trong hàm f
, thì biến a
sẽ không kết thúc vòng đời sau khi f
được gọi.
Ví dụ:
function createCounter() {
let count = 0
function increase() {
return ++count
}
return increase
}
const counter = createCounter()
console.log(counter()) // 1
console.log(counter()) // 2
console.log(counter()) // 3
Seealso
Tham khảo thêm về tính chất này ở khái niệm Closure.
Declare a Variable with var
Keyword
Nếu dùng var
để khai báo biến thì biến sẽ có global scope hoặc function scope tùy vào vị trí khai báo:
- Khai báo bên ngoài hàm thì biến mang global scope.
- Khai báo bên trong hàm thì biến mang function scope.
Ví dụ 1:
var a = 10 // global scope
{
var b = 11 // global scope
}
Ví dụ 2:
function f() {
var a = 9 // function scope
console.log(a) // 9
}
console.log(a) // a is not defined
Khi dùng từ khóa var
, ta có thể tái khai báo một biến nhiều lần mà không bị lỗi, kể cả khi sử dụng strict mode.
var a = 1
var a = 2
console.log(a) // 2
var a
console.log(a) // 2; not undefined
Nếu lần khai báo sau không gán giá trị thì giá trị của biến không thay đổi.
Xét trường hợp ta khai báo một biến có giá trị khởi tạo và một hàm trùng tên:
var a = 1
function a() {}
console.log(a) // 1
Biến a
có giá trị là 1
là bởi vì khai báo hàm bằng từ khóa function
được hoist1 lên trước phép gán giá trị. Đoạn code trên tương đương với:
var a
function a() {}
a = 1
console.log(a) // 1
Biến khai báo bằng var
trùng tên với tham số sẽ override giá trị của đối số:
function foo(a) {
var a = 1
console.log(a)
}
foo(2) // Logs 1
Seealso
Xem thêm var - MDN Web Docs
Local Scope
Là phạm vi cục bộ, các biến mang phạm vi này không thể truy cập được từ bên ngoài khối lệnh.
- Khối lệnh có thể là hàm, vòng lặp, câu lệnh điều kiện. Cụ thể hơn, khối lệnh bắt đầu và kết thúc bởi cặp dấu ngoặc nhọn (
{}
). - Vòng đời của biến local chỉ kết thúc khi ra khỏi khối lệnh, hoặc sau khi kết thúc function scope, tức là sau khi hàm được gọi.
- Khai báo bằng
let
vàconst
ở bên trong khối lệnh mang phạm vi block scope (hay local scope). Nếu khai báolet
hoặcconst
ở bên ngoài khối lệnh, chúng sẽ mang global scope.
let a = 10 // global scope
{
let a = 11 // local scope
console.log(a) // 11
}
console.log(a) // 10
Các biến thuộc các scope khác nhau có thể trùng tên với nhau. Khi xử lý logic, sẽ ưu tiên dùng biến có phạm vi gần nhất. Trong đoạn code trên, hàm console.log()
sẽ ưu tiên sử dụng biến a = 11
.
Khi nào thì cần sử dụng
let
hoặcconst
?
let
dùng khi khai báo những tên biến mà chúng ta muốn reassign, tức gán lại cho chúng bằng cách dùng các toán tử gán, chẳng hạn như=
,+=
,-=
, etc.const
dùng khi khai báo những tên biến không nên gán lại, chẳng hạn như một mảng, hàm hoặc object (các đối tượng).
Ví dụ:
let num = 10
let str = 'Hello world'
let bool = false
const arr = [1, 2, 3]
const sum = function(a, b) {
return a + b
}
const object = {
prop: 'value'
}
Comparison
Bảng so sánh các loại khai báo biến:
var | let | const |
---|---|---|
Có thể khai báo lại | Không thể khai báo lại | Không thể khai báo lại |
Có thể gán lại giá trị | Có thể gán lại giá trị | Không thể gán lại giá trị |
Chỉ có phạm vi toàn cục và phạm vi hàm | Có thể có phạm vi khối | Có thể có phạm vi khối |
Biến được đưa lên đầu và có thể sử dụng ở bất kỳ đâu | Biến phải được khởi tạo trước khi sử dụng | Biến phải được khởi tạo trước khi sử dụng |
Có thể khai báo lại ở bất kỳ đâu trong chương trình | Có thể khai báo lại trong một khối | Không bao giờ được khai báo lại |
Window Scope
Khi khai báo biến bằng console của trình duyệt mà không sử dụng từ khóa khai báo (var
, let
, const
), ta nhận được các biến có phạm vi cửa sổ.
Về bản chất, các biến này sẽ là thuộc tính của đối tượng window
. Mà đối tượng này là một đối tượng toàn cục, nên các biến này cũng được xem là các biến toàn cục.
Các biến này chỉ hoạt động trong cửa sổ trình duyệt, không thể hoạt động trong môi trường khác, chẳng hạn như NodeJS.
// Browser console
a = "Hello world"
b = 10
console.log(a) // Hello world
console.log(b) // 10
Hai dòng khai báo ở trên tương đương với:
window.a = "Hello world"
window.b = 10
Related
table tags as Tags, file.cday as Created
from [[JS Scopes]]
sort file.ctime asc