2011-07-07 28 views
15
var name = function(n) { 
    var digits = ['one','two','three','four']; 
    return digits[n]; 
} 

var namenew = (function() { 
    digits = ['one','two','three','four']; 
    return function(n) { 
     return digits[n]; 
    } 
}()); 

Cả hai phiên bản đều cho kết quả tương tự, tuy nhiên phiên bản thứ hai nhanh hơn phiên bản đầu tiên.Hiệu suất Javascript khi đóng

Như tôi đã hiểu, phiên bản đầu tiên thực hiện chức năng mỗi khi phiên bản thứ hai lưu trữ kết quả thực hiện. Đó là điều làm tôi bối rối với tư cách là một lập trình viên OOPS chức năng/thường xuyên.

Làm cách nào để có thể lưu một hàm với ngữ cảnh bên trong? Điều gì đang xảy ra dưới mui xe? Có thể một số xin làm rõ?

+1

Nó tạo ra một đối tượng có chứa danh sách chữ số, cộng với một phương pháp. –

Trả lời

13

Câu trả lời thực sự cho câu hỏi đó dài khoảng 3 trang. Nhưng tôi cố gắng làm cho nó càng ngắn càng tốt. ECMA-/Javascript là tất cả về Execution ContextsObject. Có ba loại Ngữ cảnh cơ bản trong ECMAscript: Global context, Function contextseval contexts.

Mỗi khi bạn gọi một hàm, công cụ của bạn sẽ sinh ra nó trong chính nó function context. Ngoài ra, có một số được gọi là Activation object được tạo. đối tượng bí ẩn này là một phần của một function context trong đó bao gồm ra tối thiểu:

  • [[chuỗi Phạm vi]]
  • giá trị đối tượng
  • bối cảnh "này"
  • Hoạt

Có thể có nhiều thuộc tính trên các công cụ khác nhau, nhưng ba yêu cầu này cho bất kỳ việc thực hiện ES nào. Tuy nhiên, trở lại chủ đề. Nếu một ngữ cảnh chức năng được gọi, tất cả parent contexts (hoặc nhiều hơn là precisly, các Activation objects từ các bối cảnh phụ huynh) được sao chép vào tài sản [[Scope]]. Bạn có thể nghĩ thuộc tính này giống như một mảng, chứa các đối tượng (Kích hoạt). Bây giờ, bất kỳ thông tin liên quan đến chức năng nào được lưu trữ trong đối tượng Kích hoạt (các tham số chính thức, các biến, các khai báo hàm).

Trong ví dụ của bạn, biến số digits được lưu trữ trong đối tượng Kích hoạt cho namenew. Thứ hai khi hàm ẩn danh bên trong được tạo, nó thêm rằng Activation object vào thuộc tính [[Scope]] của nó.Khi bạn gọi digits[n] ở đó, trước tiên, Javascript sẽ tìm biến đó trong đối tượng Kích hoạt riêng của mình. Nếu không thành công, tìm kiếm sẽ đi vào Scopechain. Và thì đấy, chúng tôi đã tìm thấy biến vì chúng ta đã sao chép AO từ hàm ngoài.

Tôi đã viết quá nhiều cho một câu trả lời ngắn, nhưng để thực sự đưa ra câu trả lời hay cho câu hỏi đó bạn phải giải thích một số kiến ​​thức cơ bản về ES ở đây. Tôi đoán đó chỉ là đủ để cung cấp cho bạn một ý tưởng những gì thực sự xảy ra "dưới mui xe" (có rất nhiều điều cần biết, nếu bạn muốn đọc thêm tôi sẽ cung cấp cho bạn một số tài liệu tham khảo).


Bạn hỏi cho nó, bạn nhận được nó:

http://dmitrysoshnikov.com/ecmascript/javascript-the-core/

8

Chức năng đầu tiên tạo lại digits mỗi khi được thực thi. Nếu đó là một mảng lớn thì điều này là không tốn kém.

Cửa hàng chức năng thứ hai digits trong ngữ cảnh chỉ được chia sẻ với namenew. Mỗi khi namenew được thực hiện, nó chỉ thực hiện một thao tác đơn lẻ: return digits[n].

Ví dụ như thế này sẽ không hiển thị bất kỳ mức tăng đáng chú ý nào về hiệu suất, nhưng với hiệu suất của các mảng/đối tượng/chức năng cuộc gọi rất lớn sẽ được cải thiện đáng kể.

Trong phối cảnh OOP, sử dụng đóng theo cách này tương tự như lưu trữ dữ liệu trong một biến tĩnh.


Đừng quên rằng namenew đang nhận được kết quả của hàm đóng cửa. Bản thân đóng cửa chỉ được thực hiện sau khi.

+0

Thật không may, tôi hiểu tất cả những gì bạn đã đề cập. Những gì tôi đang tìm kiếm là những gì đang xảy ra 'Dưới mui xe' – Kiran