Hướng dẫn scope javascript
Javascript có một vài khái niệm liên quan đến "Scope", không một khái niệm nào trong số chúng là dễ hiểu đối với một new JavaScript developer(JS dev), thậm chí là cả những JS dev đã có kinh nghiệm. Trong bài viết này, tôi sẽ cố gắng giải thích cặn kẽ nhất về các khái niệm liên quan đến Scope trong JS. Bài viết hướng tới những ai muốn tìm hiểu sâu hơn về các từ như là Show
Trước hết, ta sẽ bắt đầu với những khái niệm cơ bản: What is Scope?Trong JS, scope đề cập đến
ngữ cảnh hiện tại trong code của bạn. Scope có thể được xác định trên What is Global Scope?Trước khi bạn viết một dòng code JS, bạn đang ở nơi mà chúng ta gọi là
Global scope vừa là bạn tốt cũng vừa là cơn ác mộng tồi tệ đối với bạn, bạn sẽ chạy dòng code mà không có vấn đề gì với global scope (thường là đụng độ namespaces ). Bạn thường nghe mọi người than vãn " Global scope thật là tồi tệ ..", nhưng không bao giờ thực sự có lý do tại sao. Thực sự thì Global scope không phải là tồi tệ, bạn cần nó để tạo nên các Modules/ API truy cập thông qua các scopes. Bạn phải sử dụng nó như là lợi thế của mình và không có vấn đề trở ngại nào.Nếu bạn đã từng sử dụng JQuery trước đây, và ngay khi bạn làm thế này:
Bạn đang truy cập JQuery ở Global scope, chúng ta có thể tham khảo cách truy cập trong một namespace. Namespace đôi khi là một từ có thể hoán chuyển cho từ "scope", nhưng thường là đề cập đến scope mức cao nhất. Trong trường hợp này, JQuery nằm trong scope global và cũng là namespace của chúng ta. Namespace Jquery được định nghĩa trong global scope, hoạt động như một namespace cho JQuery như mọi thứ bên trong nó sẽ biến thành phần tử con bên trong namespace. What is Local Scope?Local scope đề cập đến bất kỳ scope nào được xác định qua global scope. Có một global scope, và mỗi function định nghĩa bên trong chúng (nested) local scope. Bất cứ function nào được định nghĩa bên trong một function khác đều có local scope được kết nối với function bên ngoài. Nếu tôi định nghĩa một function và tạo các biến bên trong nó, các biến đấy trở thành local scope. Ví dụ:
Bất kỳ scope items nào cũng đều không tồn tại, hay nói cách khác là không hiểu được ở global scope - trừ khi được truyền ra ngoài, điều đó có nghĩa là nếu tôi định nghĩa một function hoặc một variable trong một scope mới, thì nó không thể được truy cập từ scope bên ngoài scope hiện tại (scope mới được tạo). Một ví dụ đơn giản:
Kết quả chỉ ra rằng, ở global scope không thể truy cập đến biến Function scopeTất cả các scopes trong JS chỉ được tạo ra bởi
Lexical ScopeTiếp theo ta sẽ tìm hiểu về
Bạn sẽ nhận thấy rằng,
Làm việc với Lexical scope
cũng khá là dễ dàng, các biến/object/ function được định nghĩa ở parent scope, đều có sẵn trong scope chain. Để dễ tưởng tượng hơn, hãy theo dõi biến
Điều quan trọng nhất cần phải nhớ là Lexical scope không làm theo chiều ngược lại. Hãy theo dõi ví dụ theo hướng ngược lại:
Bạn có thể return một tham chiếu đến biến Scope ChainScope chain thiết lập cho mỗi scope một function nhất định. Mỗi function lại định nghĩa nested scope riêng như ta đã biết, và mỗi function được định nghĩa trong một function khác đều là local scope được liên kết với function bên ngoài - sự kết nối ấy được gọi là chain. Khi giải quyết một biến, JS bắt đầu với scope bên trong, sau đó tìm kiếm dần mở rộng ra bên ngoài cácbiến/object/function cho đến khi chúng được tìm thấy. ClosuresClosures có mối quan hệ râts chặt chẽ với Lexical scope. Một ví dụ tốt hơn của làm thế nào mọi thứ bên Closure hoạt động. Bạn có thể thấy khi quay lại function reference - một cách sử dụng thực tế hơn. Bên trong một scope, chúng ta có thể truy cập bất cứ gì đã khai báo ở scope cha:
Khái niệm closure chúng ta sử dụng ở đây để chỉ scope bên trong mà
kết quả khi gọi
Sau một hai lần gán vào biến
Scope and thisMỗi scope sẽ hiểu với một biến
Cũng có một vài vấn đề ta phải đối mặt khi sử dụng
Bạn có thể thấy
Đây là cách có thể bạn đã thấy, bằng cách này, giá trị mang tính "tạm thời" của Thay đổi scope với bind(), call(), apply()Đôi khi bạn cần điều khiển các scope phụ thuộc vào những gì bạn đang tìm kiếm. Một ví dụ mô tả:
Giá trị
cách sử dụng
Điều quan trọng cần phải nhớ khi sử dụng
Bạn sẽ để
.bind()khi dùng
Ta có thể sửa lại để function không bị gọi ngay taị thời thời điểm nó được định nghĩa:
Nhưng với sự thay đổi như trên, thì ta lại tạo ra một function thực sự không cần thiết, điều này sẽ thực sự kém về performance nếu chúng ta đang ở trong một vòng lặp mà các sự kiện listener đang được ràng buộc. Để giải quyết thì ta sẽ vận dụng
Bằng cách này, function sẽ không bị gọi ngay, các scopes cũng được thay đổi nếu cần, tuy nhiên, các đối số lại phải chờ để được duyệt đến. Bài tham khảo: Javascipt scope |