Tại sao “$ (). Ready (handler)” không được khuyến nghị?


88

Từ trang web tài liệu API jQuery choready

Cả ba cú pháp sau đều tương đương:

  • $ (tài liệu) .ready (trình xử lý)
  • $ (). sẵn sàng (trình xử lý) (điều này không được khuyến nghị)
  • $ (trình xử lý)

Sau khi làm bài tập về nhà - đọc và chơi với mã nguồn , tôi không biết tại sao

$().ready(handler) 

không được khuyến khích. Cách đầu tiên và cách thứ ba hoàn toàn giống nhau, tùy chọn thứ ba gọi hàm sẵn sàng trên đối tượng jQuery được lưu trong bộ nhớ cache với document:

rootjQuery = jQuery(document);
...
...

// HANDLE: $(function)
// Shortcut for document ready
} else if ( jQuery.isFunction( selector ) ) {
    return rootjQuery.ready( selector );
}

Nhưng hàm sẵn sàng không có tương tác với bộ chọn của các phần tử nút đã chọn, readyMã nguồn:

ready: function( fn ) {
    // Attach the listeners
    jQuery.bindReady();
        // Add the callback
    readyList.add( fn );
        return this;
},

Như bạn có thể thấy, nó chỉ thêm lệnh gọi lại vào hàng đợi nội bộ ( readyList) và không thay đổi hoặc sử dụng các phần tử trong tập hợp. Điều này cho phép bạn gọi readyhàm trên mọi đối tượng jQuery.

Giống:

  • bộ chọn thông thường : $('a').ready(handler) DEMO
  • Bộ chọn vô nghĩa : $('fdhjhjkdafdsjkjriohfjdnfj').ready(handler) DEMO
  • Bộ chọn không xác định : $().ready(handler) DEMO

Cuối cùng ... cho câu hỏi của tôi: Tại sao $().ready(handler)không được khuyến khích?


60
@ChaosPandion: Đối với tôi, có vẻ như anh ấy cố gắng hiểu các công cụ mà anh ấy sử dụng như mu bàn tay. Tôi sẽ không chính xác gọi đó là nỗ lực lãng phí.
Jon

5
Câu hỏi hay. Nếu ai quan tâm, đây là so sánh hiệu suất ... cho thấy (ít nhất là trong Chrome) rằng phiên bản "không được đề xuất" thực sự nhanh nhất.
James Allardice

5
Một câu hỏi hay hơn là tại sao những cái này lại tồn tại, nó phải là một phương thức tĩnh ( $.readyví dụ) và không yêu cầu xây dựng một đối tượng jQuery ngay từ đầu.
Esailija

2
@Esailija tạo nên điểm tốt nhất. Trừ khi jQuery có kế hoạch cung cấp một số loại .ready()khả năng cho các phần tử riêng lẻ, không có lý do gì để xây dựng một đối tượng jQuery.

2
@ChaosPandion. Bạn không thể sử dụng mà ... $.readyđã được thực hiện bởi một hàm jQuery nội bộ, hãy tìm kiếm mã nguồn ready:.
gdoron đang hỗ trợ Monica

Câu trả lời:


88

Tôi đã nhận được câu trả lời chính thức từ một trong những nhà phát triển jQuery:

$().ready(fn)chỉ hoạt động vì $()từng là lối tắt đến $(document) (jQuery <1.4)
Vì vậy, $().ready(fn)một mã có thể đọc được.

Nhưng mọi người đã từng làm những điều như $().mouseover()và tất cả những điều điên rồ khác.
và mọi người phải làm gì $([])để có được một đối tượng jQuery rỗng

Vì vậy, trong 1.4, chúng tôi đã thay đổi nó để $()tạo ra một jQuery trống và chúng tôi chỉ làm $().ready(fn)việc để không làm hỏng nhiều mã

$().ready(fn) nghĩa là bây giờ chỉ được vá trong lõi để làm cho nó hoạt động bình thường cho trường hợp kế thừa.

Vị trí tốt nhất cho readychức năng là vậy $.ready(fn), nhưng đó là một quyết định thiết kế thực sự cũ và đó là những gì chúng tôi có bây giờ.


Tôi hỏi anh ấy:

Bạn có nghĩ rằng $ (fn) dễ đọc hơn $ (). Ready (fn) ?!

Câu trả lời của anh ấy là:

Tôi luôn làm $ (tài liệu) .ready (fn) trong các ứng dụng thực tế và thường chỉ có một khối tài liệu sẵn sàng trong ứng dụng, nó không giống như một thứ bảo trì.

Tôi nghĩ $ (fn) cũng khá khó đọc , nó chỉ là Một điều mà bạn phải biết công việc ™ ...


1
Có lý, jQuery khá nghiêm túc về khả năng tương thích ngược
Esailija

@Esailija: Nếu họ nghiêm túc như vậy, họ đã không chuyển đổi hành vi của $()họ ngay từ đầu (ngốc nghếch như hành vi đó có thể đã xảy ra) . Mặt khác, bạn đúng. Họ không phải lúc nào cũng có xu hướng thực hiện các thay đổi đột phá, như đã được thể hiện khi họ cố gắng thay đổi .attr(), sau đó hoàn nguyên nhanh chóng vài ngày sau đó. Điều này đã ràng buộc họ vào một số quyết định thiết kế không may ở thời kỳ đầu (và giữa đời).

3
@gdoron +1 vì lấy thẳng từ miệng ngựa.

2
@gdoron +1 để nhận được câu trả lời thực sự. Và, vâng, chúng tôi đã ở khá gần trong nhận thức của mình.
VisioN

" it just A Thing That You Have To Know Works ™ ..." Cũng như vậy $(selector[, context])$(html[, ownerDocument]). Trên thực tế, bạn cũng có thể chỉ sử dụng jQuery()thay vì sử dụng $()nếu vấn đề phải-biết-nó-hoạt-động. Hoặc tại sao thậm chí sử dụng jQuery?
JAB

11

Vì các tùy chọn khác nhau thực hiện khá nhiều điều giống như bạn đã chỉ ra, nên đã đến lúc đội mũ của người viết thư viện và đưa ra một số phỏng đoán.

  1. Có lẽ người dùng jQuery muốn có $()sẵn để sử dụng trong tương lai (nghi ngờ $().readylà nó được ghi nhận là có tác dụng, ngay cả khi không được khuyến khích; nó cũng sẽ gây ô nhiễm ngữ nghĩa $nếu được viết chữ đặc biệt).

  2. Một lý do thực tế hơn nhiều: phiên bản thứ hai là phiên bản duy nhất không kết thúc gói document, vì vậy nó dễ bị hỏng hơn khi duy trì mã. Thí dụ:

    // BEFORE
    $(document).ready(foo);
    
    // AFTER: works
    $(document).ready(foo).on("click", "a", function() {});

    Đối lập điều này với

    // BEFORE
    $().ready(foo);
    
    // AFTER: breaks
    $().ready(foo).on("click", "a", function() {});
  3. Liên quan đến những điều trên: readycó một điều kỳ lạ ở chỗ nó (là phương thức duy nhất?) Sẽ hoạt động giống nhau cho dù đối tượng jQuery có bao bọc gì đi nữa (ngay cả khi nó không bao bọc bất cứ thứ gì như trường hợp ở đây). Đây là một sự khác biệt lớn so với ngữ nghĩa của các phương thức jQuery khác, vì vậy việc dựa vào nó một cách cụ thể không được khuyến khích.

    Cập nhật: Như nhận xét của Esailija đã chỉ ra, từ góc độ kỹ thuật readythực sự nên là một phương thức tĩnh vì nó hoạt động như thế này.

Cập nhật # 2: Đào tại nguồn, có vẻ như tại một số điểm trong nhánh 1.4 $()đã được thay đổi để phù hợp $([]), trong khi ở 1.3 nó hoạt động như thế nào $(document). Sự thay đổi này sẽ củng cố những lý do trên.


Tôi chưa bao giờ thấy mã như thế mặc dù điều này, các thành ngữ cũ là$(document).ready( function(){ //your code here } );
Esailija

Tôi không thể hiểu bản cập nhật thứ hai, bạn có thể giải thích thêm một số chi tiết được không? Tôi đã tìm kiếm các phiên bản cũ hơn, nhưng không thể tìm thấy bất kỳ sự khác biệt nào cho vấn đề đối tượng jQuery trống này.
gdoron đang hỗ trợ Monica

@gdoron: Ý tôi là sự thay đổi từ selector = selector || documentsang if(!selector) return this.
Jon

4

Tôi sẽ nói nó chỉ đơn giản là thực tế là $()trả về một đối tượng rỗng trong khi $(document)không áp dụng ready()cho những thứ khác nhau của bạn ; nó vẫn hoạt động, nhưng tôi sẽ nói rằng nó không trực quan.

$(document).ready(function(){}).prop("title") // the title
$().ready(function(){}).prop("title")  //null - no backing document

1
Có, những nhận thức giống nhau trong câu trả lời này . Vì vậy, những thay đổi đã diễn ra trong phiên bản 1.4, phiên bản đã phát hành chính sách hoàn trả mới.
VisioN

Tôi chưa bao giờ thấy ai đó thay đổi tiêu đề tài liệu trong khi đính kèm lệnh gọi lại sẵn sàng, Và bạn có thể đơn giản làm điều đó với vani js mà không cần jQuery . Tôi không nói nó có thể không phải là câu trả lời, nhưng nó không phải là một lý do chính đáng.
gdoron đang hỗ trợ Monica

Cũng không có tính chất tài liệu hoặc các phương pháp có thể được xích qua$()
Alex K.

2
@AlexK. quan điểm của anh ấy là không ai trong thực tế thực sự mắc xích .readyvì đó là một thành ngữ đã được thiết lập tốt để không. Chắc chắn có một cơ hội lý thuyết về việc ai đó làm điều này nhưng tôi chưa bao giờ thấy mã làm điều đó (đó không phải là một lập luận tốt nhưng bạn biết đấy: D).
Esailija

2
Có thể vì phương pháp cơ hội lý thuyết này không được khuyến khích , vì nó có hành vi khác nhau trong các bản phát hành khác nhau.
VisioN

3

Nhiều khả năng đây chỉ là một lỗi tài liệu và cần được khắc phục, nhược điểm duy nhất khi sử dụng $().ready(handler)là tính dễ đọc. Chắc chắn, lập luận rằng $(handler)cũng không thể đọc được. Tôi đồng ý, đó là lý do tại sao tôi không sử dụng nó .

Bạn cũng có thể tranh luận rằng một phương pháp này nhanh hơn phương pháp khác. Tuy nhiên, bạn có thường gọi phương thức này đủ lần liên tiếp trên một trang để nhận thấy sự khác biệt không?

Cuối cùng thì nó phụ thuộc vào sở thích cá nhân. Không có nhược điểm khi sử dụng $().ready(handler)khác với đối số khả năng đọc. Tôi nghĩ rằng tài liệu là thiếu hàng đầu trong trường hợp này.


+1! Bạn đã hoàn toàn đúng! Bạn sẽ thích đọc câu trả lời jQuery chính thức. Tôi đã thêm nó như một câu trả lời.
gdoron đang hỗ trợ Monica

2

Chỉ để làm rõ ràng rằng có một số điểm không nhất quán trong ba, thêm vào đó tôi đã thêm biểu mẫu thứ tư thường được sử dụng: (function($) {}(jQuery));

Với đánh dấu này:

<div >one</div>
<div>two</div>
<div id='t'/>

và mã này:

var howmanyEmpty = $().ready().find('*').length;
var howmanyHandler = $(function() {}).find('*').length;
var howmanyDoc = $(document).ready().find('*').length;
var howmanyPassed = (function($) { return $('*').length; }(jQuery));
var howmanyYuck = (function($) {}(jQuery));
var howmanyYuckType = (typeof howmanyYuck);

$(document).ready(function() {
    $('#t').text(howmanyEmpty + ":" + howmanyHandler + ":" 
        + howmanyDoc + ":" + howmanyPassed + ":" + howmanyYuckType);
});

Kết quả hiển thị của div từ câu lệnh cuối cùng là: 0: 9: 9: 9: undefined

VẬY, chỉ có phiên bản Trình xử lý và Tài liệu là phù hợp với quy ước jQuery về việc trả lại thứ gì đó sử dụng được khi chúng nhận được bộ chọn tài liệu và với biểu mẫu Đã qua, bạn phải trả lại thứ gì đó (Tôi sẽ nghĩ vậy, nhưng hãy đặt nó vào để hiển thị "bên trong" nó có một cái gì đó).

Đây là một phiên bản fiddle của điều này cho những người tò mò: http://jsfiddle.net/az85G/


Tôi không thể hiểu vấn đề là nó không tìm thấy bất cứ thứ gì, ngữ cảnh bạn đã cung cấp cho jQuery nullnên .find('*').lengthtrả về 0 . Bạn có thấy điều gì xấu với hành vi (hiển nhiên) này không?
gdoron đang hỗ trợ Monica

@gdoron - Tôi không thấy có gì xấu với hành vi này, tôi chỉ muốn chỉ ra sự khác biệt so với khi nó CÓ bộ chọn KHÔNG rỗng - lưu ý rằng bộ chọn trống này có khả năng là lý do tại sao các nhận xét "nhanh hơn" được ghi nhận ở nơi khác vì nó có một đối tượng nhỏ hơn để xử lý, nhưng KHÔNG trả về một đối tượng và không phải là "không xác định" trong trường hợp đó. Tôi thực sự thích câu hỏi và đã ủng hộ nó :)
Mark Schultheiss

Lý do là tại sao nó nhanh hơn, bởi vì điều kiện "ngắt" đầu tiên của ctor là if(!selector) return thisnếu bạn đưa ra thứ gì khác, thì có regexvà những thứ khác đang diễn ra ... Cảm ơn bạn đã vui lòng gửi lời ... trả lời điều này (quái, nó không phải là thư viện của tôi :-)).
gdoron đang hỗ trợ Monica

Đúng, tôi chưa nghiên cứu phần cụ thể này của cơ sở mã, tôi đã hack phần lõi để đưa vào các bản sửa lỗi liên tục nhưng không phải phần đó. Tôi muốn xem jQuery(document).ready(function(){});biểu mẫu trong cơ sở mã của chúng tôi hiện tại vì có các mức độ chuyên môn khác nhau về jQuery và điều "rõ ràng nhất" đối với những người mới rằng nó LÀ một hàm xử lý sự kiện cho jQuery.
Mark Schultheiss

0

Tôi nghĩ rằng điều này thực sự là để dễ đọc hơn bất cứ điều gì khác.

Cái này không biểu cảm bằng

$().ready(handler);

như

$(document).ready(handler)

Có lẽ họ đang cố gắng quảng bá một số dạng jQuery thành ngữ.


3
$(document).ready(handler) dễ đọc hơn $(handler) đó là khuyến cáo ...
gdoron đang hỗ trợ Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.