เหตุใดจึงไม่แนะนำให้ใช้“ $ (). ready (handler)”


88

จากไซต์เอกสาร jQuery APIสำหรับready

ไวยากรณ์ทั้งสามต่อไปนี้เทียบเท่ากัน:

  • $ (เอกสาร). พร้อม (ตัวจัดการ)
  • $ () พร้อม (ตัวจัดการ) (ไม่แนะนำ)
  • $ (ตัวจัดการ)

หลังจากทำการบ้าน - อ่านและเล่นกับซอร์สโค้ดฉันไม่รู้ว่าทำไม

$().ready(handler) 

ไม่แนะนำ วิธีแรกและวิธีที่สามเหมือนกันทุกประการตัวเลือกที่สามเรียกใช้ฟังก์ชันพร้อมใช้งานบนวัตถุ jQuery ที่แคชด้วยdocument:

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

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

แต่ฟังก์ชันพร้อมไม่มีการโต้ตอบกับตัวเลือกขององค์ประกอบโหนดที่เลือกreadyซอร์สโค้ด:

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

อย่างที่คุณเห็นมันเพิ่มการเรียกกลับไปยังคิวภายใน ( readyList) และไม่เปลี่ยนแปลงหรือใช้องค์ประกอบในชุด สิ่งนี้ช่วยให้คุณเรียกใช้readyฟังก์ชันบนวัตถุ jQuery ทุกตัว

ชอบ:

  • ตัวเลือกปกติ : $('a').ready(handler) DEMO
  • ตัวเลือกไร้สาระ : $('fdhjhjkdafdsjkjriohfjdnfj').ready(handler) สาธิต
  • ตัวเลือกที่ไม่ได้กำหนด : $().ready(handler) DEMO

สุดท้าย ... คำถามของฉัน: ทำไม$().ready(handler)ไม่แนะนำ?


60
@ChaosPandion: สำหรับฉันดูเหมือนว่าเขาพยายามที่จะเข้าใจเครื่องมือที่เขาใช้เหมือนหลังมือ ฉันจะไม่เรียกว่าเสียแรงเปล่า
จอน

5
คำถามที่ดี. หากใครสนใจนี่คือการเปรียบเทียบประสิทธิภาพ ... ซึ่งแสดงให้เห็น (ใน Chrome อย่างน้อย) ว่าเวอร์ชัน "ไม่แนะนำ" นั้นเร็วที่สุดจริงๆ
James Allardice

5
คำถามที่ดีกว่าคือเหตุใดสิ่งเหล่านี้จึงมีอยู่ทั้งหมดควรเป็นวิธีการแบบคงที่ ( $.readyเช่น) และไม่จำเป็นต้องสร้างวัตถุ jQuery ตั้งแต่แรก
Esailija

2
@Esailija ทำให้จุดที่ดีที่สุดของทั้งหมด เว้นแต่ jQuery วางแผนที่จะให้ความสามารถบางอย่าง.ready()สำหรับแต่ละองค์ประกอบก็ไม่ควรมีเหตุผลที่จะสร้างวัตถุ jQuery

2
@ChaosPandion. คุณไม่สามารถใช้ว่า ... $.readyถูกใช้ไปแล้วโดยฟังก์ชั่นภายใน jQuery ready:ค้นหารหัสที่มาสำหรับ
gdoron ให้การสนับสนุน Monica ใน

คำตอบ:


88

ฉันได้รับคำตอบอย่างเป็นทางการจากหนึ่งในผู้พัฒนา jQuery:

$().ready(fn)ใช้งานได้เพราะ$()เคยเป็นทางลัดไปยัง$(document) (jQuery <1.4)
ดังนั้นจึง$().ready(fn)เป็นรหัสที่อ่านได้

แต่คนเคยทำสิ่งที่ชอบ$().mouseover()และความบ้าคลั่งอื่น ๆ ทุกประเภท
และผู้คนต้องทำ$([])เพื่อให้ได้วัตถุ jQuery ที่ว่างเปล่า

ดังนั้นใน 1.4 เราเปลี่ยนมันเพื่อ$()ให้ jQuery ว่างเปล่าและเราเพิ่ง$().ready(fn)ทำงานเพื่อไม่ให้โค้ดจำนวนมากเสียหาย

$().ready(fn) ตอนนี้ได้รับการแก้ไขอย่างแท้จริงในแกนกลางเพื่อให้ทำงานได้อย่างถูกต้องสำหรับกรณีเดิม

สถานที่ที่ดีที่สุดสำหรับreadyฟังก์ชั่นคือ$.ready(fn)แต่เป็นการตัดสินใจในการออกแบบที่เก่ามากและนั่นคือสิ่งที่เรามีในตอนนี้


ฉันถามเขา:

คุณคิดว่า $ (fn) อ่านได้มากกว่า $ () พร้อม (fn) หรือไม่!

คำตอบของเขาคือ:

ฉันมักจะทำ $ (document) .ready (fn) ในแอปจริงและโดยปกติแล้วจะมีบล็อกพร้อมเอกสารเพียงชุดเดียวในแอปซึ่งไม่เหมือนกับการบำรุงรักษา

ฉันคิดว่า $ (fn) ก็อ่านไม่ออกเหมือนกันมันเป็นแค่สิ่งที่คุณต้องรู้ Works ™ ...


1
มีเหตุผล jQuery ค่อนข้างจริงจังเกี่ยวกับความสามารถในการย้อนกลับ
Esailija

@Esailija: หากพวกเขาที่ร้ายแรงพวกเขาจะไม่ได้เปลี่ยนพฤติกรรมของ$()ในสถานที่แรก(ตามที่โง่เป็นพฤติกรรมที่อาจได้รับ) ในทางกลับกันคุณพูดถูก พวกเขาไม่ได้มีแนวโน้มที่จะทำการเปลี่ยนแปลงที่ไม่สมบูรณ์เสมอไปดังที่แสดงให้เห็นเมื่อพวกเขาพยายามเปลี่ยนแปลง.attr()จากนั้นก็เปลี่ยนกลับอย่างรวดเร็วในสองสามวันต่อมา สิ่งนี้ผูกมัดพวกเขาไว้กับการตัดสินใจออกแบบในช่วงต้น (และวัยกลางคน) ที่โชคร้าย

3
@gdoron +1 เพื่อรับตรงจากปากม้า.

2
@gdoron +1 เพื่อรับคำตอบที่แท้จริง และใช่เราใกล้เข้ามาแล้วในการรับรู้ของเรา
VisioN

" มันเป็นเพียงสิ่งที่คุณต้องรู้ธิ ™ ..." ดีเพื่อให้มีและ$(selector[, context]) $(html[, ownerDocument])ในความเป็นจริงคุณอาจใช้jQuery()แทนได้เช่นกัน$()หากการต้องรู้ว่ามันเป็นปัญหา หรือทำไมถึงใช้ jQuery เลย?
JAB

11

เนื่องจากตัวเลือกที่แตกต่างกันทำในสิ่งเดียวกันกับที่คุณชี้ให้เห็นถึงเวลาสวมหมวกนักเขียนห้องสมุดและคาดเดาบางอย่าง

  1. บางทีคน jQuery อาจต้องการให้$()ใช้งานได้ในอนาคต (น่าสงสัยเนื่องจากได้$().readyรับการบันทึกไว้ว่าใช้งานได้แม้ว่าจะไม่แนะนำก็ตาม แต่ก็อาจก่อให้เกิดมลพิษทางความหมาย$หากมีการระบุแบบพิเศษ)

  2. เหตุผลที่เป็นประโยชน์กว่ามาก: เวอร์ชันที่สองเป็นเวอร์ชันเดียวที่ไม่จบลงด้วยการตัดdocumentดังนั้นจึงง่ายกว่าที่จะทำลายเมื่อรักษารหัส ตัวอย่าง:

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

    ตรงกันข้ามกับ

    // BEFORE
    $().ready(foo);
    
    // AFTER: breaks
    $().ready(foo).on("click", "a", function() {});
    
  3. ที่เกี่ยวข้องกับข้างต้น: readyเป็นความประหลาดในแง่ที่เป็น (วิธีเดียว?) ที่จะทำงานเหมือนกันไม่ว่าวัตถุ jQuery จะห่อหุ้มอะไรก็ตาม (แม้ว่าจะไม่ได้ห่ออะไรก็ตามในกรณีนี้) นี่เป็นความแตกต่างที่สำคัญจากความหมายของวิธีการ jQuery อื่น ๆ ดังนั้นการพึ่งพาสิ่งนี้โดยเฉพาะจึงไม่ถูกต้อง

    อัปเดต:ตามที่ความคิดเห็นของ Esailija ชี้ให้เห็นว่าจากมุมมองทางวิศวกรรมreadyควรเป็นวิธีการคงที่เพราะมันทำงานเช่นนี้

ปรับปรุง # 2:ขุดที่มาดูเหมือนว่าที่จุดใน 1.4 สาขาบาง$()ก็เปลี่ยนให้ตรงกับ$([])ในขณะที่ใน 1.3 $(document)มันทำตัวเหมือน การเปลี่ยนแปลงนี้จะตอกย้ำเหตุผลข้างต้น


ฉันไม่เคยเห็นรหัสแบบนี้มาก่อนสำนวนเก่าคือ$(document).ready( function(){ //your code here } );
Esailija

ฉันไม่เข้าใจการอัปเดตครั้งที่สองช่วยอธิบายเพิ่มเติมได้ไหม ฉันค้นหาเวอร์ชันเก่ากว่า แต่ไม่พบความแตกต่างใด ๆ สำหรับปัญหาวัตถุ jQuery ที่ว่างเปล่านี้
gdoron ให้การสนับสนุน Monica

@gdoron: ฉันหมายถึงการเปลี่ยนจากselector = selector || documentเป็นif(!selector) return this.
จอน

4

ฉันจะบอกว่ามันเป็นเพียงความจริงที่$()ส่งคืนวัตถุว่างเปล่าในขณะที่คุณ$(document)ไม่ได้ใช้ready()กับสิ่งอื่น มันยังใช้งานได้ แต่ฉันจะบอกว่ามันไม่ใช้งานง่าย

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

1
ใช่การรับรู้เดียวกันอยู่ในคำตอบนี้ ดังนั้นการเปลี่ยนแปลงจึงเกิดขึ้นในเวอร์ชัน 1.4 ซึ่งออกนโยบายการคืนสินค้าใหม่
VisioN

ผมไม่เคยเห็นใครบางคนเปลี่ยนชื่อเอกสารแนบในขณะที่การเรียกกลับพร้อมและคุณสามารถทำมันได้ด้วยวานิลลาโดยไม่ต้อง js jQuery ฉันไม่บอกว่ามันอาจจะไม่ใช่คำตอบ แต่ก็ไม่ใช่เหตุผลที่ดี
gdoron ให้การสนับสนุน Monica

ไม่มีคุณสมบัติของเอกสารหรือวิธีการใดสามารถผูกมัดได้ผ่าน$()
Alex K.

2
@AlexK. ประเด็นของเขาคือในความเป็นจริงแล้วไม่มีใครล่ามโซ่.readyเพราะมันเป็นสำนวนที่ดีที่ไม่ควรทำ แน่นอนว่ามีโอกาสทางทฤษฎีที่จะมีคนทำสิ่งนี้ แต่ฉันไม่เคยเห็นรหัสทำแบบนั้น (ซึ่งไม่ใช่ข้อโต้แย้งที่ดี แต่คุณรู้ไหม: D)
Esailija

2
อาจเป็นเพราะไม่แนะนำให้ใช้วิธีการให้โอกาสทางทฤษฎีนี้เนื่องจากมีพฤติกรรมที่แตกต่างกันในรุ่นต่างๆ
VisioN

3

มากกว่าที่จะเป็นไปได้ว่านี่เป็นเพียงข้อบกพร่องของเอกสารและควรได้รับการแก้ไขข้อเสียเพียงอย่างเดียวในการใช้$().ready(handler)คือความสามารถในการอ่าน แน่นอนว่าเถียงว่า$(handler)อ่านไม่ออก ฉันเห็นด้วยนั่นคือเหตุผลที่ฉันไม่ใช้มันว่าทำไมฉันไม่ได้ใช้มัน

คุณยังสามารถโต้แย้งว่าวิธีหนึ่งเร็วกว่าอีกวิธีหนึ่ง อย่างไรก็ตามคุณเรียกใช้วิธีนี้บ่อยครั้งเพียงใดในหนึ่งครั้งติดต่อกันในหน้าเดียวเพื่อสังเกตความแตกต่าง

สุดท้ายแล้วมันขึ้นอยู่กับความชอบส่วนบุคคล ไม่มีข้อเสียในการใช้$().ready(handler)อื่นนอกจากอาร์กิวเมนต์ความสามารถในการอ่าน ฉันคิดว่าเอกสารนี้ไม่ได้เป็นผู้นำในกรณีนี้


+1! คุณคิดถูกจริงๆ! คุณจะชอบอ่านคำตอบอย่างเป็นทางการของ jQuery ผมเพิ่มเป็นคำตอบ
gdoron ให้การสนับสนุน Monica

2

เพียงเพื่อให้เห็นได้ชัดว่ามีความไม่สอดคล้องกันในสามอย่างนี้บวกกับฉันได้เพิ่มแบบฟอร์มที่สี่ที่ใช้บ่อย: (function($) {}(jQuery));

ด้วยมาร์กอัปนี้:

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

และรหัสนี้:

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);
});

ผลลัพธ์ที่แสดงของ div จากคำสั่งสุดท้ายคือ: 0: 9: 9: 9: ไม่ได้กำหนด

ดังนั้นเฉพาะเวอร์ชัน Handler และ Doc เท่านั้นที่สอดคล้องกับหลักการ jQuery ในการส่งคืนสิ่งที่ใช้งานเมื่อได้รับตัวเลือกเอกสารและด้วยแบบฟอร์ม Passed คุณจะต้องส่งคืนบางสิ่ง (ฉันจะไม่ทำเช่นนี้ฉันคิดว่า แต่ใส่ไว้เฉยๆ เพื่อแสดง "ข้างใน" มันมีอะไรบางอย่าง)

นี่คือเวอร์ชั่นซอสำหรับคนขี้สงสัย: http://jsfiddle.net/az85G/


ฉันไม่สามารถมองเห็นสิ่งที่เป็นปัญหากับว่ามันไม่ได้หาอะไรบริบทที่คุณให้สำหรับ jQuery เป็นnullเพื่อ.find('*').lengthกลับ0 คุณพบสิ่งที่ไม่ดีกับพฤติกรรม (ชัดเจน) นี้หรือไม่?
gdoron ให้การสนับสนุน Monica

@gdoron - ฉันไม่พบสิ่งที่ไม่ดีกับพฤติกรรมนี้ฉันแค่อยากจะชี้ให้เห็นความแตกต่างเมื่อเทียบกับเมื่อมีตัวเลือกที่ไม่เป็นโมฆะ - โปรดทราบว่าตัวเลือกที่ว่างเปล่านี้น่าจะเป็นสาเหตุที่ความคิดเห็น "เร็วกว่า" ถูกบันทึกไว้ ที่อื่นเนื่องจากมีอ็อบเจ็กต์ที่เล็กกว่าในการประมวลผล แต่ DOES ส่งคืนอ็อบเจ็กต์และไม่ "ไม่ได้กำหนด" ในอินสแตนซ์นั้น ฉันชอบคำถามนี้มากและโหวตให้คะแนน :)
Mark Schultheiss

สาเหตุที่มันเร็วกว่าก็เพราะว่า ctor เงื่อนไข "แตก" ครั้งแรกคือif(!selector) return thisถ้าคุณให้อย่างอื่นมีregexและสิ่งอื่น ๆ เกิดขึ้น ... ขอบคุณสำหรับคำพูดที่กรุณา ... ฉันคิดว่าฉันอาจจะขอให้ทีม jQuery ตอบสิ่งนี้ (นรกไม่ใช่ห้องสมุดของฉัน:-))
gdoron ให้การสนับสนุน Monica

ใช่ฉันไม่ได้ศึกษาส่วนนี้ของฐานรหัสโดยเฉพาะฉันได้แฮ็กคอร์เพื่อทำการแก้ไขจุดบกพร่องระหว่างกัน แต่ไม่ใช่ส่วนนั้น ฉันชอบที่จะเห็นjQuery(document).ready(function(){});แบบฟอร์มในฐานรหัสของเราในปัจจุบันเนื่องจากมีความเชี่ยวชาญ jQuery ในระดับที่แตกต่างกันและเป็นที่ "ชัดเจนที่สุด" สำหรับคนใหม่ ๆ ว่าเป็นฟังก์ชันตัวจัดการเหตุการณ์สำหรับ jQuery
Mark Schultheiss

0

ฉันคิดว่านี่เป็นสิ่งที่อ่านได้ง่ายกว่าสิ่งอื่นใด

อันนี้ไม่แสดงออก

$().ready(handler);

เช่น

$(document).ready(handler)

บางทีพวกเขาอาจพยายามส่งเสริม jQuery สำนวนบางรูปแบบ


3
$(document).ready(handler)อ่านได้ง่ายกว่า$(handler)ที่แนะนำ ...
gdoron สนับสนุน Monica
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.