2012-05-03 39 views
55

Người dân ở đây thường đề nghị để cache jQuery đối tượng được tạo ra từ một yếu tố DOM, giống như với mã này:

$('#container input').each(function() { 
    $(this).addClass('fooClass'); 
    $(this).attr('data-bar', "bar"); 
    $(this).css('background-color', 'red'); 
}); 
  • Liệu bộ nhớ đệm đối tượng jQuery thực sự cải thiện hiệu suất của mã của chúng tôi?
  • Điều gì xảy ra "hậu trường" khi bạn chuyển một phần tử DOM tới hàm tạo jQuery?
+16

'$ (this)' rõ ràng có nghĩa là "' (this) 'đô la". – BoltClock

+0

Bạn nên luôn nhớ cache, nhưng trong ví dụ cụ thể này, bạn thậm chí không cần phải làm điều đó. Chỉ cần tận dụng chuỗi jQuery: '$ (this) .addClass ('fooClass'). Attr ('data-bar'," bar ") .ss ('background-color', 'red');' –

Trả lời

51

Trong jQuery tag info cảnh báo này xuất hiện:

Các jQuery Hàm $() là tốn kém. Gọi nó liên tục là vô cùng hiệu quả.

Vâng ... đó là sự thật duy nhất cho selectors chuỗi, mà được phân tích với regex để tìm hiểu xem họ là:

quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/ 

Sau đó, nếu chuỗi là một chọn (trừ id), jQuery đi qua DOM để tìm một trận đấu với find chức năng đắt tiền của mình:

} else if (!context || context.jquery) { 
    return (context || rootjQuery).find(selector); 
} 

vì vậy, có nó là đắt tiền, nhưng điều đó chỉ đúng cho selectors!

Nếu chúng ta vượt qua một DOMElement, hành động chỉ jQuery làm là tiết kiệm tham số DOMElement như bối cảnh của đối tượng jQuery mới được tạo ra và thiết lập chiều dài của bối cảnh đến 1:

// Handle $(DOMElement) 
if (selector.nodeType) { 
    this.context = this[0] = selector; // Selector here is a DOMElement 
    this.length = 1; 
    return this; 
} 

tôi đã làm some tests with jsPerf , và tôi thấy rằng thực sự bộ nhớ đệm đối tượng jQuery chỉ có một hiệu ứng nhỏ:

Bar chart, described below

Trong Chrome nó chậm hơn chỉ 7%. (Trong IE đó là một chút ít quan trọng hơn: 12%.)

+24

Lưu ý: Trả lời câu hỏi của riêng bạn được khuyến khích một cách rõ ràng * Bạn hoàn toàn có thể đăng câu hỏi mà bạn đã biết câu trả lời nếu nó chưa xuất hiện trên trang web. Điều này không hề khuyến khích hỏi lại các câu hỏi phổ biến. Các bản sao sẽ bị đóng và xóa. –

+0

Trong cả hai trường hợp, bạn sẽ tiết kiệm ít nhất một lần gọi hàm mỗi lần. – Christoph

+0

So sánh không đúng ... Có sự khác biệt lớn về hiệu suất. –

14

Để trả lời câu hỏi thứ hai của bạn, nhìn vào source:

// Handle $(DOMElement) 
if (selector.nodeType) { 
    this.context = this[0] = selector; 
    this.length = 1; 
    return this; 
} 
+1

Đây là một ứng dụng nhỏ đẹp để xem mã nguồn: http://james.padolsey.com/jquery/#v=git&fn=jQuery.fn.init – Joe

+3

Bây giờ, một bộ chọn chuỗi rõ ràng sẽ có một biểu đồ khác nhau. – Joe

+0

@JoeTuskan. Tôi đã xây dựng bình luận của bạn trong câu trả lời cập nhật của tôi. – gdoron

10

liên quan đến sự khác biệt hiệu suất Với, nếu bạn đang tìm kiếm một so sánh trực tiếp giữa hai, rất hữu ích khi xóa bất kỳ mã bổ sung nào có thể làm lệch kết quả, như chọn DOM và các phương thức khác không liên quan trực tiếp.

http://jsperf.com/this-cost/2

enter image description here

Trong một bối cảnh thế giới thực hơn, sự khác biệt tương đối là nhỏ như thử nghiệm của bạn cho thấy

Một điều cần lưu ý là mỗi khi bạn tạo một đối tượng jQuery, bộ nhớ cần phải được cấp phát cho nó, điều này làm tăng thêm công việc mà bộ thu gom rác cần làm.

Vì vậy, tôi nghĩ lý do mọi người đề xuất lưu vào bộ nhớ đệm là từ phần nào của quan điểm chính. Thêm công việc đang được thực hiện, trong khi nó thường sẽ không có một tác động đáng chú ý, cuối cùng yêu cầu một số chi phí mà có thể dễ dàng tránh được.

+0

Giải thích tốt !!! +1 – Gaurav123

+0

So sánh này tốt hơn nhiều so với so sánh của câu trả lời được chấp nhận. –

8

Một điều mà tất cả các bài kiểm tra hiệu suất thời gian chạy ở đây bỏ lỡ là một yếu tố nữa chính:

Mạng băng thông.

Caching $(this) vào biến cục bộ nói chung sẽ giảm kích thước tập lệnh của bạn, đặc biệt khi được rút gọn (vì this không thể giảm từ bốn ký tự).

Cân nhắc: đầu ra minified

function hello(text) { 
    $(this).attr(); 
    $(this).css(); 
    $(this).data(); 
    $(this).click(); 
    $(this).mouseover(); 
    $(this).mouseleave(); 
    $(this).html(text); 
} 
hello('Hello world'); 

Đóng trình biên dịch là

function hello(a){$(this).attr();$(this).css();$(this).data();$(this).click();$(this).mouseover();$(this).mouseleave();$(this).html(a)}hello("Hello world"); 

Điều này tiết kiệm 39 byte (20%). Bây giờ xem xét:

function hello(name) { 
    var $this = $(this); 
    $this.attr(); 
    $this.css(); 
    $this.data(); 
    $this.click(); 
    $this.mouseover(); 
    $this.mouseleave(); 
    $this.html(name); 
} 
hello('Hello world'); 

Sản lượng minified là

function hello(b){var a=$(this);a.attr();a.css();a.data();a.click();a.mouseover();a.mouseleave();a.html(b)}hello("Hello world"); 

Điều này tiết kiệm 74 byte (37%), gần gấp đôi tiết kiệm byte của chúng tôi. Rõ ràng, tiết kiệm trong thế giới thực trong các kịch bản lớn sẽ thấp hơn, nhưng bạn vẫn đứng để đạt được sự giảm đáng kể kích thước của kịch bản của bạn bằng bộ nhớ đệm.

Thực sự, chỉ có một nhược điểm để lưu vào bộ nhớ cache $(this). Bạn nhận được hiệu suất thời gian chạy tối thiểu nhưng có thể đo lường được. Quan trọng hơn, bạn có thể giảm số lượng byte di chuyển qua dây và chuyển trực tiếp thành nhiều đô la hơnfaster page loads equal more sales.

Khi bạn xem xét theo cách đó, bạn thực sự có thể nói rằng có thể định giá đô la có giá trị để lặp lại $(this) và không lưu vào bộ nhớ cache.

+0

+1, Mặc dù nó là một câu trả lời cho lý do tại sao bạn nên cache 'this' không' $ (this) 'bởi vì bạn có thể nhận được kết quả tương tự với' this.value; this.tagName; this.className; this.nodeType; điều này....' – gdoron

+0

@gdoron, có sự khác biệt lớn giữa việc sử dụng các phương thức DOM và jQuery thô; chúng không phải lúc nào cũng có thể hoán đổi cho nhau. ('addClass',' data', animation ...) Bên cạnh đó, vẫn có sự khác biệt 3 byte cho mỗi cuộc gọi giữa 'var a = $ (this); một ...; một ...; 'và' var a = this; $ (a) ...; $ (a) ...; ' – josh3736

+0

Nếu bạn đang gzipping các tập tin của bạn, bạn sẽ thường thấy rằng kích thước tập tin là một chút lớn hơn như là kết quả của bộ nhớ đệm như vậy. Trong ví dụ của bạn, nó chỉ có một vài byte khác biệt, 111 so với 115 byte, nhưng nó nhấn mạnh điểm. Tôi không biết tại sao điều này lại xảy ra, nhưng tôi thường thấy điều này là đúng. –

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