2010-05-18 46 views
6

Trong ví dụ nàyChuỗi hàm phạm vi bên trong JavaScript?

var a = 1; 
(function(x) { 
    function inner() { 
     alert(a); 
     alert(x); 
     alert(y); 
    } 
    var y = 3; 
    inner(); 
})(2); 

Khi nào function inner được tạo ra? trong thời gian thực hiện hoặc phân tích cú pháp thời gian của chức năng ẩn danh bên ngoài?

Có gì trong chuỗi phạm vi function inner?

Sự khác nhau giữa ngữ cảnh thực thi và chuỗi phạm vi của function inner là gì?

Cảm ơn bạn đã khai sáng trước cho tôi!

Trả lời

7

Khi nào chức năng bên trong được tạo? trong thời gian thực hiện hoặc phân tích cú pháp thời gian của chức năng ẩn danh bên ngoài?

Một được tạo mỗi lần hàm bên ngoài được thực hiện.

Có gì trong chuỗi phạm vi hàm bên trong?

Khi bạn thực thi nó, thực thi đó nhận được một đối tượng biến (về mặt kỹ thuật spec gọi đây là "đối tượng ràng buộc của môi trường biến"); được hỗ trợ bởi đối tượng biến được tạo cho cuộc gọi hàm bên ngoài đã tạo ra inner; được hỗ trợ bởi đối tượng biến toàn cục. Vì vậy:

+------------------------------+ 
| global variable obj   | 
+------------------------------+ 
    ^
    | 
    +-----------------------------+ 
    | variable obj for outer call | 
    +-----------------------------+ 
    ^
     | 
     +-----------------------------+ 
     | variable obj for inner call | 
     +-----------------------------+ 

Ngữ cảnh thực hiện chức năng bên trong là gì?

Mọi cuộc gọi hàm đều có ngữ cảnh thực thi riêng. Tôi không hoàn toàn chắc chắn tôi hiểu những gì đang được hỏi ở đây.

Bạn có thể đọc lên trên tất cả các công cụ này (nếu bạn sẵn sàng để lội qua các thuốc giải độc của văn xuôi cương lên) tại mục 10 của the spec, và đặc biệt section 10.4.3: "Bước vào Mã hàm".

+0

ngữ cảnh thực hiện được tạo vào thời gian chạy, chuỗi phạm vi được tạo tại thời điểm xác định (không chắc chắn đó là đúng hạn), câu hỏi của tôi là: sự khác biệt giữa ngữ cảnh thực thi và chuỗi phạm vi chức năng bên trong là gì? Quá trình tạo ngữ cảnh thực hiện là gì? cám ơn! – nandin

+1

@Ding: Có, chuỗi phạm vi được quyết định theo vị trí hàm được xác định. Bạn có thể biết bằng cách nhìn vào một hàm trong nguồn những gì các định danh nằm trong phạm vi cho nó, và chúng đến từ đâu. Nhưng các hàm không có ngữ cảnh thực thi, chỉ có * các cuộc gọi * cho các hàm hoạt động. Ngữ cảnh thực thi bao gồm đối tượng biến tạo thành cơ chế thời gian chạy của chuỗi phạm vi, cũng như các thứ khác, giống như giá trị 'this' này. Bạn rõ ràng có một quan tâm trong thực sự biết làm thế nào công cụ này hoạt động (đó là tuyệt vời!) Và vì vậy tôi chỉ có thể nói: Đọc Sect 10 (esp 10.3 & 4) của spec để biết chi tiết. :-) –

9

Chức năng inner được tạo ngay trước khi chức năng ẩn danh được thực thi, bởi quy trình Variable Instantiation.

Các [[Scope]] của inner khi nó được thực hiện bao gồm:

  1. Các Object Variable trống inner (đó là trống rỗng vì không có khai báo biến/chức năng bên trong nó)
  2. Các Object Variable của hàm nặc danh, trong đó có x, yinner.
  3. Đối tượng toàn cầu, chứa a và các thuộc tính khác ...
 
    Global (3)   Anonymous VO (2)  inner VO (1) 
    ________    ________    ________ 
    | a = 1 | <--------- | x = 2 | < -------- |  | 
    | ... |   | y = 3 |    ¯¯¯¯¯¯¯¯ 
    ¯¯¯¯¯¯¯¯    | inner | 
         ¯¯¯¯¯¯¯¯ 

Sửa: Để làm rõ câu hỏi thứ hai của bạn:

phần chênh lệch giữa bối cảnh thực hiện và chuỗi phạm vi chức năng bên trong là gì?

Hai khái niệm khác nhau, bối cảnh thực thi được tạo ngay trước một đoạn mã (được mã can be mã toàn cầu, mã chức năng hoặc mã eval).

Tôi nghĩ rằng điều này có thể được dễ dàng hơn để giải thích với mã của bạn:

var a = 1; 
(function(x) {  // Step 1 
    function inner() { 
     alert(a); 
     alert(x); 
     alert(y); 
    } 
    var y = 3; 
    inner();   // Step 3 
})(2);    // Step 2 

Trong Bước 1, chức năng ẩn danh là created, phạm vi hiện tại (chỉ chứa các đối tượng toàn cầu) được lưu trữ trong này thời điểm trên chức năng [[Scope]] tài sản.

Trong Bước 2, chức năng ẩn danh này được thực thi, một bối cảnh thực hiện mới được tạo ra (một function code execution context), tại thời điểm này một môi trường từ vựng mới được tạo (Object Variable của chức năng này được tạo ra), tất cả các chức năng số nhận dạng đối số (trong trường hợp này chỉ x), số nhận dạng của khai báo hàm (inner) và số nhận dạng khai báo biến (y) bị ràng buộc là thuộc tính không thể xóa của đối tượng biến mới này (phạm vi từ vựng mới).

Trong Bước 3 chức năng inner được thực thi, điều này tạo ra một bối cảnh thực hiện mới, một Object Variable được tiêm vào chuỗi phạm vi, nhưng trong trường hợp này vì không có gì được khai báo bên trong inner và nó không có bất kỳ các thông số chính thức, nó sẽ chỉ là một đối tượng trống.

Xem thêm câu hỏi this, phần đầu tiên tôi nói về câu lệnh with nhưng trong phần thứ hai, đó là về các hàm.

+0

cảm ơn CMS, như mọi khi, câu trả lời tuyệt vời! – nandin

+0

Bạn được chào đón @Ding, được chỉnh sửa để trả lời câu hỏi thứ hai của bạn ... – CMS

+0

điều này thực sự khó đọc (http://www.ecma-international.org/publications/standards/Ecma-262.htm), bạn có thể đề xuất mã nguồn mở JS engine? làm thế nào về V8? cám ơn! – nandin

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