Khái niệm
Phạm vi biến cho biết một tên biến có thể được truy cập ở đâu trong chương trình. Hiểu đúng phạm vi giúp tránh ghi đè ngoài ý muốn và làm cho từng phần mã nguồn có trách nhiệm rõ ràng hơn.
Ví dụ biến cục bộ và biến bên ngoài hàm
message = "Ben ngoai ham"
def show_message():
message = "Ben trong ham"
print(message)
show_message()
print(message)
program ScopeDemo;
var
message: String;
procedure ShowMessage;
var
message: String;
begin
message := 'Ben trong ham';
Writeln(message);
end;
begin
message := 'Ben ngoai ham';
ShowMessage;
Writeln(message);
end.
#include <stdio.h>
char message[] = "Ben ngoai ham";
void show_message(void) {
char message[] = "Ben trong ham";
printf("%s\n", message);
}
int main(void) {
show_message();
printf("%s\n", message);
return 0;
}
#include <iostream>
using namespace std;
string message = "Ben ngoai ham";
void showMessage() {
string message = "Ben trong ham";
cout << message << endl;
}
int main() {
showMessage();
cout << message << endl;
return 0;
}
string message = "Ben ngoai ham";
void ShowMessage() {
string message = "Ben trong ham";
Console.WriteLine(message);
}
ShowMessage();
Console.WriteLine(message);
let message = "Ben ngoai ham";
function showMessage() {
let message = "Ben trong ham";
console.log(message);
}
showMessage();
console.log(message);
let message: string = "Ben ngoai ham";
function showMessage(): void {
let message: string = "Ben trong ham";
console.log(message);
}
showMessage();
console.log(message);
package main
import "fmt"
var message = "Ben ngoai ham"
func showMessage() {
message := "Ben trong ham"
fmt.Println(message)
}
func main() {
showMessage()
fmt.Println(message)
}
fn show_message() {
let message = "Ben trong ham";
println!("{}", message);
}
fn main() {
let message = "Ben ngoai ham";
show_message();
println!("{}", message);
}
Ghi chú theo ngôn ngữ
Muốn thay đổi trực tiếp biến toàn cục từ bên trong hàm trong Python, thường phải khai báo global. Nếu không, tên đó sẽ được hiểu là biến cục bộ mới.
Pascal cho phép khai báo biến cục bộ ngay trong thủ tục hoặc hàm bằng khối var riêng. Biến cục bộ có ưu tiên truy cập cao hơn biến cùng tên ở mức ngoài.
C có nhiều mức phạm vi như block scope, file scope và function scope. Khi cần dùng chung dữ liệu ở nhiều nơi, nên cân nhắc kỹ trước khi đặt ở file scope.
C++ kế thừa các mức phạm vi của C và bổ sung namespace để tổ chức mã rõ nhơn. Biến có thể bị che khuất bởi biến cùng tên ở phạm vi hẹp hơn.
C# nhấn mạnh rõ ràng: biến cục bộ che khuất biến ngoài khi khởi tạo trong cùng phạm vi, nhưng IDE thường cảnh báo khi điều này xảy ra.
JavaScript với let và const có block scope giống C. Trước đó, var có function scope và gây nhiều lỗi ngầm do hoisting. Nên dùng let/const trong mã mới.
TypeScript áp dụng cùng các quy tắc phạm vi như JavaScript. Hệ thống kiểu tĩnh giúp phát hiện sớm các lỗi liên quan đến phạm vi biến.
Go có block scope rõ ràng. Toán tử := khai báo biến mới trong phạm vi hiện tại và có thể vô tình che khuất biến cùng tên ở phạm vi rộng hơn.
Rust cho phép shadowing: có thể khai báo lại biến cùng tên trong cùng phạm vi bằng let. Cách này khác với biến có thể thay đổi (mut) và thường dùng khi chuyển đổi kiểu của giá trị.
Kết luận
Phạm vi biến là nền tảng để tổ chức hàm rõ ràng và an toàn. Khi một hàm tự gọi lại chính nó, ngoài phạm vi còn cần quan tâm đến điều kiện dừng, đó là nội dung của Đệ quy.
Bình luận