07/09/2018, 17:19

You Don't Know JS: Scope & Closures

What is Scope? Một trong những khả năng cơ bản của hầu hết tất cả các ngôn ngữ lập trình đó là khả năng lưu(store) giá trị vào biến(variable), và sau đó có thể sửa, xóa hay lấy giá trị đó. Thực tế khả năng lưu lại giá trị vào biến và lấy giá trị ra từ biến là việc chuyển đổi trạng thái của ...

What is Scope?

  • Một trong những khả năng cơ bản của hầu hết tất cả các ngôn ngữ lập trình đó là khả năng lưu(store) giá trị vào biến(variable), và sau đó có thể sửa, xóa hay lấy giá trị đó. Thực tế khả năng lưu lại giá trị vào biến và lấy giá trị ra từ biến là việc chuyển đổi trạng thái của chương trình.

  • Nhưng trong app của chúng ta việc lưu một giá trị vào một biến diễn ra như nào, những biến đó "sống" ở đâu, nói cách khác những biến đó được lưu ở đâu trong app, và câu hỏi quan trong nhất, app của chúng ta sẽ làm thế nào để tìm một biến khi cần.

  • Những câu hỏi trên đã chỉ ra rằng chúng ta cần có một nguyên tắc và thiết kế rõ ràng trong việc lưu lại biến và sau đó lấy biến ra để sử dụng.

  • Chúng ta gọi tất cả những nguyên tắc để lưu biến là lấy biến là "Scope"

Understanding Scope

  • var a = 2; Cách mà Hệ thống hiểu dòng code trên như sau:
  1. Engine : chịu trách nhiệm thực thi code của chúng ta

  2. Compiler : có trách nhiệm compile những dòng code trên sang một loại mã có thể thự thi bởi Engine

  3. Scope : sẽ tập hợp lại tất cả các biến (những đoạn đã định nghĩa ký tự var) sau đó gán cho những biến này những luật để mà có thể access những biến này.

  • Scope được gắn biền với những block { }

Ví dụ :

  • Đối với function : function(){ // SCOPE OF FUNCTION HERE}
  • Đối với Oject : obj = {// SCOPE OF OBJECT IS HERE}
  • Đối với Class : Class Person {// SCOPE Ò CLASS HERE}
var obj = {
  last_name: "a",
  first_name: "b",
  full_name: function(){return this.last_name + this.first_name}
}
  • Scope cos tên là obj
  • Trong Scope obj có những thành phần là last_name, first_name, full_name

Engine/Scope Conversation

  • Cách một biến được tìm trong Scope
function foo(a) {
    console.log( a );
}

foo( 2 );

Engine: Hey Scope, I have an RHS reference for foo. Ever heard of it?

Scope: Why yes, I have. Compiler declared it just a second ago. He's a function. Here you go.

Engine: Great, thanks! OK, I'm executing foo.

Engine: Hey, Scope, I've got an LHS reference for a, ever heard of it?

Scope: Why yes, I have. Compiler declared it as a formal parameter to foo just recently. Here you go.

Engine: Helpful as always, Scope. Thanks again. Now, time to assign 2 to a.

Engine: Hey, Scope, sorry to bother you again. I need an RHS look-up for console. Ever heard of it?

Scope: No problem, Engine, this is what I do all day. Yes, I've got console. He's built-in. Here ya go.

Engine: Perfect. Looking up log(..). OK, great, it's a function.

Engine: Yo, Scope. Can you help me out with an RHS reference to a. I think I remember it, but just want to double-check.

Scope: You're right, Engine. Same guy, hasn't changed. Here ya go.

Engine: Cool. Passing the value of a, which is 2, into log(..).

Nested Scope

  • Như đã nói Scope là một tập hợp các nguyên tắc để app có thể tìm kiếm các biến thông qua tên, vậy liệu Scope sẽ làm như nào khi một biến không thể tìm thấy trong Scope đó? Nó sẽ trả về là không tìm thấy hay làm gì tiếp?
    => Khi không tìm thấy biến trong Scope hiện tại thì Engine sẽ tiếp tục hỏi đến Scope bao bên ngoài Scope hiện tại để tìm kiếm, Cho đến khi nó hỏi đến Global scope

  • Cách một biến đc tìm trong Nested Scope

function foo(a) {
    console.log( a + b );
}

var b = 2;

foo( 2 );

Engine: "Hey, Scope of foo, ever heard of b? Got an RHS reference for it."

Scope: "Nope, never heard of it. Go fish."

Engine: "Hey, Scope outside of foo, oh you're the global Scope, ok cool. Ever heard of b? Got an RHS reference for it."

Scope: "Yep, sure have. Here ya go."

  • Tìm hiểu về đoạn mã sau:
function foo(a) {
    var b = a * 2;

    function bar(c) {
        console.log( a, b, c );
    }

    bar(b * 3);
}
foo( 2 );
  • Có 3 nested scope trong đoạn mã trên

Screenshot from 2016-01-27 12:59:08.png

  • Scope 1: Là global scope, chỉ bao gồm 1 phần tử có identifier(id) là foo
  • Scope 2: Là scope có tên foo bao gồm 3 phần tử có id là a, b và bar
  • Scope 3: là scope có tên bar bao gồm 1 pgaanf tử có id là c

Look-ups

  • Tên của biến trong 1 scope chính là ID của phần tử đó

ví dụ:

var obj {
  a: 1,
  b: 2
}

=> a, b chính là các id của biến a, b trong scope obj

  • Nếu trong cùng 1 scope mà có phần tử trùng ID (cùng tên) thì Scope sẽ nhận biến đc định nghĩa cuối cùng

  • Một ID sẽ được tìm cho đến khi tìm thấy hoặc tìm đến Global Scope.

Thanks

Thsnk you alot. Give me any feedback or leave a comment so that I can get better!(thankyou)

0