2012-06-21 47 views
5

Tôi đang cố hiểu các quy tắc phạm vi JavaScript. Những gì tôi đã đọc trong sách giáo khoa và tài liệu là khó hiểu. Có vẻ như với tôi rằng JavaScript là một ngôn ngữ phạm vi tĩnh (hoặc lexically) - khi cố gắng liên kết một tên biến với một biến (định nghĩa), cấu trúc từ vựng của mã được sử dụng.Phạm vi JavaScript và ngữ cảnh thực hiện

Ngữ cảnh thực thi có vẻ tương tự như khung ngăn xếp trên ngăn xếp cuộc gọi. Mỗi bối cảnh thực hiện có một đối tượng biến mà tất cả các biến cục bộ (của hàm liên kết) được định nghĩa. Các đối tượng biến được liên kết với nhau để cung cấp một 'chuỗi phạm vi' từ đối tượng biến ở trên cùng của ngăn xếp đến đối tượng biến ở dưới cùng của ngăn xếp (đối tượng cửa sổ). Chuỗi phạm vi này được tìm kiếm từ trên xuống dưới trong các tên biến liên kết với các biến. Điều này rất giống với các ngôn ngữ có phạm vi tĩnh như C/C++/Java.

Có một sự khác biệt quan trọng đối với C/C++/Java - có thể truy cập một biến được xác định trong một hàm có khung ngăn xếp không còn trên ngăn xếp cuộc gọi, như trong ví dụ bên dưới:

var color = "red"; 
var printColor; 

function changeColor() { 
    var color = "green"; 

    printColor = function(msg) { 
     alert(msg + color); 
    } 
    printColor("in changeColor context, color = "); // "green" 
} 

changeColor(); 

// stack frame for "changeColor" no longer on stack 
// but we can access the value of the variable color defined in that function 

printColor("in global context, color = "); // "green" 

Tôi có được quyền này không? Có vấn đề nào khác mà tôi nên biết không?

Cảm ơn trước

+4

Một bài đăng rất kỹ lưỡng nhấn HN ngày hôm nay chạm vào điều này: [Ngữ cảnh thực thi & ngăn xếp trong JavaScript là gì?] (Http://davidshariff.com/blog/what-is-the-execution-context-in- javascript /) –

+2

Điều này được gọi là * đóng *. Hàm bạn gán cho 'printColor' có quyền truy cập vào tất cả các biến được định nghĩa trong' changeColor' ngay cả sau khi hàm kết thúc. Tôi không biết làm thế nào đây là trong C. –

+0

@FelixKling gần như. tuy nhiên changeColor được định nghĩa trên phạm vi toàn cục, do đó phạm vi của nó sẽ không bao giờ được thu gom rác. – webduvet

Trả lời

2

Đây thực sự là một sự khác biệt lớn giữa C/C++ và JavaScript: JavaScript là một, thu gom rác ngôn ngữ tài liệu tham khảo-tính, có nghĩa là đối tượng có thể được khai hoang bởi động cơ khi họ không còn bất kỳ tham chiếu nào cho họ. Chức năng bạn chỉ định cho printColor không có trong ngăn xếp, mỗi lần, vì nó sẽ ở trong C hoặc C++; nó được phân bổ động và sau đó được gán cho một biến ngoài phạm vi hiện tại của bạn. Do đó, khi luồng điều khiển trả về từ changeColor, hàm ẩn danh vẫn có số tham chiếu là vì bên ngoài printColor đề cập đến nó và do đó có thể sử dụng được từ phạm vi bên ngoài.

Vì vậy, ví dụ bạn không phải là quá nhiều của một vấn đề Phạm vi - thì rõ ràng rằng bạn khai báo printColorngoài về phạm vi chức năng của changeColor. Khi bạn xác định changeColor, nó closes giá trị tăng cao printColor vào phạm vi chức năng mới, làm cho nó có thể truy cập được. Giống như Combat nói, nếu bạn thêm một var đến thứ hai định nghĩa, bên trong của printColor, nó bạn sẽ shadow là người đầu tiên printColor tuyên bố và nó sẽ không thể truy cập bên ngoài mà chức năng khối.

Theo như các vấn đề khác cần lưu ý, có, có một số ít, nhưng hãy xem nhận xét trên bài đăng gốc của bạn để có một khởi đầu tốt.

+0

Than ôi, tôi có thể đã đọc sai câu hỏi (w.r.t. biến 'color'), nhưng tôi nghĩ những gì tôi viết vẫn giữ nước. –

+0

Khi bạn nói rằng printColor không có trong ngăn xếp, tôi đoán bạn có nghĩa là đối tượng đại diện cho printColor. Khi printColor được gọi, khung thực thi/khung ngăn xếp được đẩy lên ngăn xếp. Hay tôi hiểu sai? – asterix

0

Nó luôn luôn đi xuống đến phạm vi từ vựng mà chức năng được thực hiện với chuỗi phạm vi của nó khi nó được xác định, không phải khi nó được gọi.

Hàm ẩn danh được xác định trong phạm vi cục bộ của hàm changeColor thay vì phạm vi toàn cục.Do đó khi nó được thực hiện một lần nữa, nó in ra màu xanh lá cây được liệt kê trong phạm vi cục bộ của hàm changeColor.

Các vấn đề liên quan