Static và Dynamic Scoping
Xem thửScoping quyết định binding tên với đối tượng ngôn ngữ nào khi có nhiều khai báo trùng tên. Hai mô hình kinh điển: static (lexical) scoping và dynamic scoping.
Static / lexical scoping
Phạm vi quyết định bởi cấu trúc lồng nhau trên source lúc biên dịch:
- Một use của
xgắn với khai báoxtrong block/enclosing scope tĩnh gần nhất. - Hầu hết ngôn ngữ hiện đại (C, C++, Java, JavaScript module/let, Python…) theo lexical.
Ưu điểm: phân tích tĩnh, tối ưu, hiểu chương trình không cần chạy; closure bắt biến theo môi trường lexical.
Dynamic scoping
Binding phụ thuộc chuỗi lời gọi runtime — tìm khai báo gần nhất trên call stack:
- Ít phổ biến ở ngôn ngữ mainstream (một số Lisp cũ/option, một số scripting lịch sử).
- Khó phân tích tĩnh; hành vi đổi khi đổi call chain.
Ví dụ tư duy
int x = 1;
void f() { print(x); }
void g() { int x = 2; f(); }
- Static:
fin1(x toàn cục lexical), dù gọi từg. - Dynamic:
fcó thể in2nếu tìm x theo stack gọi từg.
Runtime environment (activation records) phải hỗ trợ mô hình đã chọn: lexical thường dùng static link / display; dynamic quét dynamic link trên stack.
Đang tải sơ đồ…
Ghi nhớ thi/phỏng vấn
Nhìn “free variable trong hàm lồng”: static nhìn hàm nào bao quanh trên mã nguồn; dynamic nhìn ai gọi lúc chạy. Đừng nhầm scoping với lifetime (thời gian đối tượng tồn tại) hay visibility API — liên quan nhưng không đồng nhất.
Cùng một đoạn code (g() gọi f(), cả hai đều khai báo x), hai mô hình scoping resolve x ra hai kết quả khác nhau:
Đang tải sơ đồ…