The linked video explains why closure can inflict some performance hits starting about 11:08.
Về cơ bản, anh ấy nói rằng đối với mỗi chức năng lồng nhau, nó bổ sung thêm đối tượng khác để chuỗi phạm vi và do đó việc tiếp cận các biến bên ngoài của việc đóng cửa sẽ mất ngay cả lâu.
Để tìm giá trị liên quan đến một biến, các interprer Javascript sau quá trình này:
- tìm kiếm các đối tượng phạm vi địa phương
- nếu 1 không hiệu quả, tìm kiếm các đối tượng phạm vi mẹ
- nếu 2 không hoạt động, tìm đối tượng phạm vi chính của cha mẹ
- tiếp tục tìm kiếm phạm vi gốc cho đến
- bạn tìm kiếm phạm vi toàn cầu
- và nếu vẫn không tìm thấy, hãy ném một lỗi biến không xác định.
Trong một chức năng bình thường, để tìm biến, bạn chỉ phải tìm kiếm ở đầu chuỗi phạm vi. Một đóng cửa, mặt khác, để tìm các biến cha mẹ sẽ phải tìm kiếm xuống chuỗi phạm vi, đôi khi nhiều cấp độ sâu. Ví dụ, nếu bạn đã có một số đóng cửa như thế này (lưu ý rằng đây là một rất giả tạo ví dụ):
function a (x) {
function b (y) {
return (function (z) {
return x + y + z;
})(y + y);
}
return b(x + 3);
}
Từ chức năng trong cùng, để đánh giá sự biểu hiện x + y + z
, nó phải đi qua lên ba cấp độ trong phạm vi chuỗi để tìm x, sau đó nó phải đi qua chuỗi phạm vi một lần nữa hai cấp độ để tìm y, và sau đó cuối cùng một lần để tìm z.Tổng cộng, nó phải tìm kiếm sáu đối tượng trong chuỗi phạm vi để trả lại kết quả cuối cùng.
Điều này là không thể tránh khỏi khi đóng cửa, vì các đóng bao luôn phải truy cập vào các biến mẹ. Nếu họ không ở đó sẽ không có mục đích trong việc sử dụng một đóng cửa.
Cũng lưu ý rằng trong Javascript, có một chi phí đáng kể trong việc tạo ra các chức năng, đặc biệt là đóng cửa. Lấy ví dụ, đóng cửa khá đơn giản này:
function a(x) {
return function (y) {
return x + y;
}
}
Và bạn gọi nó là thời gian khác nhau, như thế này
var x = a(1);
var y = a(2);
var z = a(3);
alert(x(3)); // 4
alert(y(3)); // 5
alert(z(3)); // 6
Bạn sẽ nhận thấy rằng chức năng trở về từ a
có để giữ những gì đã được thông qua như một đối số trong hàm cha ngay cả sau khi hàm cha đã được gọi. Điều này có nghĩa là người thông dịch phải ghi nhớ những gì bạn đã truyền vào cho mọi chức năng mà bạn đã gọi cho đến giờ.
Chỉ cần nhớ: tối ưu hóa sớm là gốc rễ của mọi điều ác. Video đang thảo luận làm cho JavaScript hoạt động hiệu quả hơn, tuy nhiên hầu hết JavaScript không bao giờ cần phải được tối ưu hóa. Nếu bạn có cuộc gọi đến một chức năng được thiết lập không đồng bộ sau khi người dùng nhấp vào nút, người dùng sẽ không bao giờ nhận thấy sự khác biệt giữa tỷ lệ phản hồi 30ms và tỷ lệ phản hồi 40ms. – zzzzBov
Các câu trả lời ở đây đều tốt. Tuy nhiên, hãy nhớ rằng video này đã được một vài năm và có thể không liên quan như t một lần. –