Mục đích của lưu ý này là có một thuật ngữ riêng biệt và chính xác cho các loại phạm vi khác nhau được sử dụng trong JS và trong các ngôn ngữ lập trình nói chung
Khán giả. kỹ sư giàu kinh nghiệm, các chuyên gia
Nhiều nhà phát triển JavaScript biết rằng JS [cũng như hầu hết các ngôn ngữ hiện có ngày nay] sử dụng phạm vi tĩnh
Chúng tôi đã thảo luận chi tiết về chủ đề này trước đây. Nếu bạn không quen thuộc với khái niệm phạm vi nói chung hoặc không biết rõ sự khác biệt giữa tĩnh và. phạm vi động, bạn có thể giải quyết hai bài viết này
- môi trường từ vựng. Lý thuyết chung
- môi trường từ vựng. Triển khai ECMAScript
Và trong ghi chú này, chúng tôi sẽ trình bày ngắn gọn rằng JS thực sự có cả ba loại phạm vi. tĩnh, động và tăng cường thời gian chạy
phạm vi tĩnhđịnh nghĩa 1. phạm vi tĩnh. một ngôn ngữ triển khai phạm vi tĩnh, nếu chỉ bằng cách xem mã nguồn, người ta có thể xác định ràng buộc được giải quyết trong môi trường nào
Phạm vi tĩnh về mặt kỹ thuật được thực hiện bằng khái niệm đóng cửa. Và ngược lại, các bao đóng có thể được triển khai một cách tự nhiên trong các ngôn ngữ có phạm vi tĩnh
Có thể có các triển khai đóng cửa khác. e. g. khi các biến miễn phí được nắm bắt dưới dạng các thuộc tính riêng của một thể hiện của lớp Đóng, mặc dù đó là một chi tiết triển khai và theo khái niệm lý thuyết, nó vẫn đang “nắm bắt” môi trường từ vựng
Ví dụ về phạm vi tĩnh
Phạm vi tĩnh JavaScriptGHI CHÚ. biến
x
cho hàmprint_x
là miễn phí, vì nó không phải là tham số cũng không phải là biến cục bộ của hàm này
Trong ví dụ trên chúng ta thấy, biến x
đó được bắt khi hàm print_x
được tạo. Và biến cục bộ x
của hàm run
không ảnh hưởng đến việc thực thi hàm print_x
phạm vi độngđịnh nghĩa 2. phạm vi tĩnh. phạm vi tĩnh về mặt kỹ thuật được triển khai một cách tự nhiên bằng cách đóng, thông qua cơ chế nắm bắt các biến tự do trong môi trường từ vựng
GHI CHÚ. ví dụ trên cũng hoạt động trong các ngôn ngữ không có bao đóng — chỉ thông qua phạm vi toàn cầu
Phạm vi động dành riêng cho các biến không được sử dụng rộng rãi trong thực tế ngày nay. Một ví dụ đáng chú ý có thể là ngôn ngữ lập trình Perl, có hỗ trợ cho cả hai loại phạm vi
Phạm vi tĩnh và động Perlđịnh nghĩa 3. phạm vi động. một ngôn ngữ triển khai phạm vi động, nếu người gọi xác định môi trường kích hoạt của callee
Nói cách khác, một người gọi [không phải là một callee như trong phạm vi tĩnh] định nghĩa các giá trị cho các biến tự do được sử dụng bởi một callee. Chúng ta thấy ví dụ ở trên dẫn đến giá trị 20
khi hàm print_x
được gọi từ hàm dynamic
, do hàm dynamic
cung cấp giá trị riêng cho biến x
Người ta có thể lập luận rằng phạm vi động đơn giản là không có ý nghĩa. Và thực sự, làm thế nào chúng ta có thể triển khai các chức năng có thể dự đoán được, nếu chúng ta thậm chí không biết các chức năng của mình sẽ được thực thi trong tương lai từ môi trường nào?
Tuy nhiên, mục đích thực tế của phạm vi động không nằm ở khả năng dự đoán mà ngược lại - trong việc tạo các hàm giao diện chung, chỉ cung cấp việc triển khai và sau đó có thể hoạt động từ bất kỳ môi trường nào miễn là môi trường này cung cấp các giá trị cho các biến cần thiết
Và các ràng buộc động như vậy thực sự là thứ chúng ta vẫn sử dụng trong nhiều ngôn ngữ ngày nay, ngay cả khi có thể không nhận thấy nó. Và JavaScript không phải là một ngoại lệ — đó là giá trị của print_x
2
định nghĩa 4. Giá trị này. trong JavaScript, giá trị
print_x
2 có phạm vi động, trừ khi được sử dụng trong hàm mũi tên
Đúng rồi. như chúng ta biết, giá trị của print_x
2 được xác định và cung cấp chính xác bởi người gọi
Trong trường hợp này, chúng tôi định nghĩa một hàm giao diện chung print_x
5, hoạt động với bất kỳ đối tượng nào, thực hiện thuộc tính x
. Và cả ba người gọi đều cung cấp giá trị chính xác cho print_x
2, giá trị này là động trong trường hợp này
GHI CHÚ. theo nguyên tắc này hoạt động OOP trong hầu hết các ngôn ngữ. một lớp chỉ là nơi lưu trữ các phương thức, được thực thi trong ngữ cảnh cần thiết, hoạt động với giá trị động
print_x
2
Một số ngôn ngữ, e. g. Python hoặc Rust thích chuyển đối số print_x
9 rõ ràng làm tham số đầu tiên. Trên thực tế, phạm vi động cho các biến có thể được thay thế đơn giản bằng cách chuyển tất cả các giá trị cần thiết làm đối số hàm. Tức là biến các biến tự do thành các biến ràng buộc — thông qua các tham số
Như chúng tôi cũng đã đề cập, các chức năng mũi tên được giới thiệu trong ES2015 sử dụng từ vựng [i. e. tĩnh] và nắm bắt print_x
2 trong môi trường từ vựng, giống như các biến khác
định nghĩa 5. Phạm vi tăng cường thời gian chạy. xảy ra khi khung kích hoạt không được xác định tĩnh và có thể bị thay đổi bởi chính callee
Loại phạm vi này trong JavaScript được giới thiệu bằng cách sử dụng hướng dẫn x
1 và x
2. Cả hai đều không được khuyến khích sử dụng. x
1 thậm chí không được dùng nữa và x
2 ở chế độ nghiêm ngặt được thực thi trong môi trường hộp cát;
Điều đó nói rằng, trên thực tế, hãy cố gắng tránh cả hai, x
1 và x
2 [chúng cũng phá vỡ mọi sự tối ưu hóa. ], tuy nhiên, thật tốt khi biết rằng loại phạm vi như vậy tồn tại