2013-02-13 20 views
7

Nếu tôi chạy mã này trong Công cụ nhà phát triển Chrome:Gỡ lỗi Tiết lộ Mô hình Mô-đun: các chức năng không nằm trong phạm vi cho đến khi được gọi?

var test = (function() { 

    var publicFunction, 
     privateFunction1, 
     privateFunction2; 

    privateFunction1 = function privateFunction1() { 
    return true; 
    }; 

    privateFunction2 = function privateFunction2() { 
    return true; 
    }; 

    publicFunction = function publicFunction() { 
    privateFunction1(); 
    debugger; 
    }; 

    return { 
    publicFunction: publicFunction 
    }; 
})(); 

tại sao privateFunction1 trong phạm vi tại breakpoint, trong khi privateFunction2 không?

Screenshot of Chrome Dev Tools

+1

Lưu ý phụ: Không có mục đích nào được phân phối bởi các biến mà bạn đã khai báo, bạn có thể (và có lẽ nên) chỉ thực hiện việc này thay vì: http://pastie.org/6150861 Vì bạn chỉ định * biểu thức hàm có tên * cho các biến đó, trên IE8 và bên dưới bạn đang tạo hai hàm cho mỗi hàm của bạn (tại hai thời điểm khác nhau). Một sự khác biệt không tạo ra sự khác biệt nào trừ khi bạn tình cờ kết nối một trình xử lý sự kiện bằng cách sử dụng một trong hai trình xử lý và cố gắng gỡ bỏ nó sau này bằng một trình xử lý khác. Thông tin thêm trên blog của tôi: [* Double-take *] (http://blog.niftysnippets.org/2010/09/double-take.html) –

+1

Vâng, tôi nghĩ * đó là vì V8 (công cụ JavaScript của Chrome) là loại bỏ 'privateFunction2' hoàn toàn bởi vì nó không được sử dụng bất cứ nơi nào (nó đã chết mã). Sau đó, tôi đã cố gắng để chứng minh nó bằng cách sử dụng nó ở nơi khác, và điều đó đã không thay đổi bất cứ điều gì. Rất, rất kỳ quặc. –

+0

Cảm ơn, tôi không biết về các vấn đề về IE với NFE. Tuy nhiên, tôi thích đặt tên biểu thức chức năng hơn khai báo, nếu chỉ vì tôi không thích cẩu. – janfoeh

Trả lời

4

Câu hỏi hấp dẫn.

privateFunction2 trong phạm vi cho publicFunction, nhưng publicFunction không bao giờ thực sự sử dụng nó. Tôi tin rằng những gì bạn thấy trong trình gỡ rối là vì V8 (công cụ JavaScript của Chrome) tối ưu hóa nội dung của các bao đóng vì nhiều lý do khác nhau (bao gồm giảm thiểu sử dụng bộ nhớ).

Theo lý thuyết, theo đặc điểm kỹ thuật, publicFunction đóng trên (có tham chiếu lâu dài) tất cả các ký hiệu trong phạm vi được xác định. Cụ thể, một execution context đã được tạo cho cuộc gọi đến chức năng ẩn danh ngoài cùng của bạn và ngữ cảnh thực thi có lexical environment với một số liên kết binding objectpublicFunction có tham chiếu ẩn danh, ẩn danh. Đối tượng liên kết đó có các thuộc tính trên đó với (theo lý thuyết) có tên là publicFunction, privateFunction1, privateFunction2 và một vài thứ khác (arguments và các thứ khác).

Nhưng vấn đề là rằng publicFunction không thực sự tham khảo bất cứ điều gì nhưng privateFunction1, và với mã tại chỗ cho nó, nó không thể tham khảo bất cứ điều gì khác. Đối với nó để tham khảo bất cứ điều gì khác, bạn sẽ phải thay đổi mã của nó, và tất nhiên họ V8 sẽ đưa ra quyết định khác. Mã số trong publicFunction không có số eval(string) hoặc new Function(string) cuộc gọi, vì vậy V8 được tự do thực hiện phân tích tĩnh trên các ký hiệu mà nó tham chiếu. Điều đó có nghĩa rằng, không có trình gỡ lỗi, không có điểm nào đối với đối tượng ràng buộc giữ các thuộc tính khác đó. Chúng không bao giờ được sử dụng.

Vì V8 là trình biên dịch tối ưu hóa mạnh mẽ (có, trình biên dịch), rõ ràng nó loại bỏ các thuộc tính đã chết khỏi đối tượng ràng buộc của ngữ cảnh thực thi.

Nếu tôi thêm một cái gì đó vào publicFunction sử dụng privateFunction2 cho bất cứ điều gì, sau đó tôi có thể tham khảo nó từ bảng điều khiển giống như tôi có thể privateFunction1.

+0

Có vẻ như bạn đã đúng: nếu tôi cung cấp cho publicFunction một tham số và đánh giá nó, mọi thứ khác sẽ xuất hiện trong phạm vi như mong đợi. Cảm ơn bạn! – janfoeh

+0

@janfoeh: Rất vui được giúp! –

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