เหตุใดจึงกำหนดฟังก์ชันที่ไม่ระบุตัวตนและส่ง jQuery เป็นอาร์กิวเมนต์


100

ฉันกำลังดูรหัสสาธิต peepcode ที่ยอดเยี่ยมจาก screencasts backbone.js ในนั้นรหัสกระดูกสันหลังจะอยู่ในฟังก์ชันที่ไม่ระบุชื่อที่ส่งผ่านวัตถุ jQuery:

(function($) {
  // Backbone code in here
})(jQuery);

ในรหัสกระดูกสันหลังของฉันฉันเพิ่งรวมรหัสทั้งหมดของฉันไว้ในเหตุการณ์ 'พร้อม' jQuery DOM:

$(function(){
  // Backbone code in here
});

ประเด็น / ข้อดีของแนวทางแรกคืออะไร? การทำเช่นนี้จะสร้างฟังก์ชันที่ไม่ระบุชื่อซึ่งจะถูกเรียกใช้ทันทีโดยที่วัตถุ jQuery ถูกส่งผ่านเป็นอาร์กิวเมนต์ของฟังก์ชันทำให้มั่นใจได้ว่า $ เป็นวัตถุ jQuery นี่เป็นเพียงจุดเดียว - เพื่อรับประกันว่า jQuery ถูกผูกไว้กับ '$' หรือมีเหตุผลอื่นในการทำเช่นนี้หรือไม่?


4
คุณควรเรียกดู SO ก่อนแทน
Alexander

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

อาจซ้ำกันได้: jQuery และ $ questions
Alexander

ดูเอกสาร jQuery ที่ซ้ำกันที่เป็นไปได้เทียบกับฟังก์ชันการเรียกตัวเองแบบไม่ระบุชื่อสำหรับความแตกต่าง
Bergi

@ Alexander แต่แล้วคนอื่น ๆ จะพบคำถามนี้ใน SO ก่อน :-)
caiosm1005

คำตอบ:


184

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

โมดูล JavaScript


(function($) {
  // Backbone code in here
})(jQuery);

นี่คือรูปแบบ "โมดูล JavaScript" ที่ใช้งานกับฟังก์ชันเรียกใช้ทันที

วัตถุประสงค์ของรหัสนี้คือเพื่อให้ "ความเป็นโมดูลาร์" ความเป็นส่วนตัวและการห่อหุ้มสำหรับโค้ดของคุณ

การใช้งานนี้เป็นฟังก์ชันที่เรียกใช้ทันทีโดย(jQuery)วงเล็บการเรียก จุดประสงค์ของการส่ง jQuery ในวงเล็บคือการกำหนดขอบเขตท้องถิ่นให้กับตัวแปรส่วนกลาง ซึ่งจะช่วยลดค่าใช้จ่ายในการค้นหา$ตัวแปรและช่วยให้การบีบอัด / การปรับให้เหมาะสมสำหรับตัวย่อที่ดีขึ้นในบางกรณี

ฟังก์ชันที่เรียกใช้ทันทีจะดำเนินการทันที ทันทีที่การกำหนดฟังก์ชันเสร็จสมบูรณ์ฟังก์ชันจะถูกเรียกใช้งาน

ฟังก์ชัน "DOMReady" ของ jQuery

นี่คือนามแฝงของฟังก์ชัน "DOMReady" ของ jQuery: http://api.jquery.com/ready/


$(function(){
  // Backbone code in here
});

ฟังก์ชัน "DOMReady" ของ jQuery จะดำเนินการเมื่อ DOM พร้อมที่จะจัดการโดยโค้ด JavaScript ของคุณ

โมดูลเทียบกับ DOM พร้อมในรหัสกระดูกสันหลัง

เป็นรูปแบบที่ไม่ดีในการกำหนดโค้ด Backbone ของคุณภายในฟังก์ชัน DOMReady ของ jQuery และอาจสร้างความเสียหายต่อประสิทธิภาพแอปพลิเคชันของคุณ ฟังก์ชันนี้จะไม่ถูกเรียกจนกว่า DOM จะโหลดและพร้อมที่จะจัดการ นั่นหมายความว่าคุณกำลังรอจนกว่าเบราว์เซอร์จะแยกวิเคราะห์ DOM อย่างน้อยหนึ่งครั้งก่อนที่คุณจะกำหนดวัตถุของคุณ

เป็นความคิดที่ดีกว่าในการกำหนดวัตถุ Backbone ของคุณนอกฟังก์ชัน DOMReady ฉันชอบที่จะทำสิ่งนี้ภายในรูปแบบโมดูล JavaScript เพื่อที่ฉันจะสามารถให้การห่อหุ้มและความเป็นส่วนตัวสำหรับโค้ดของฉันได้ ฉันมักจะใช้รูปแบบ "โมดูลการเปิดเผย" (ดูลิงก์แรกด้านบน) เพื่อให้การเข้าถึงบิตที่ฉันต้องการนอกโมดูลของฉัน

ด้วยการกำหนดวัตถุของคุณภายนอกฟังก์ชัน DOMReady และให้วิธีการอ้างอิงบางอย่างคุณกำลังอนุญาตให้เบราว์เซอร์เริ่มต้นการประมวลผล JavaScript ของคุณซึ่งอาจช่วยเร่งประสบการณ์ของผู้ใช้ นอกจากนี้ยังทำให้โค้ดมีความยืดหยุ่นมากขึ้นเนื่องจากคุณสามารถเคลื่อนย้ายสิ่งต่างๆได้โดยไม่ต้องกังวลกับการสร้างฟังก์ชัน DOMREady เพิ่มเติมเมื่อคุณย้ายสิ่งต่างๆ

คุณน่าจะใช้ฟังก์ชัน DOMReady แม้ว่าคุณจะกำหนดวัตถุ Backbone ไว้ที่อื่นก็ตาม เหตุผลก็คือแอป Backbone จำนวนมากจำเป็นต้องจัดการ DOM ในบางลักษณะ ในการดำเนินการนี้คุณต้องรอจนกว่า DOM จะพร้อมดังนั้นคุณต้องใช้ฟังก์ชัน DOMReady เพื่อเริ่มแอปพลิเคชันของคุณหลังจากที่ได้กำหนดไว้แล้ว

คุณสามารถค้นหาตัวอย่างมากมายเกี่ยวกับสิ่งนี้ได้จากเว็บ แต่นี่คือการใช้งานขั้นพื้นฐานโดยใช้ทั้งโมดูลและฟังก์ชัน DOMReady:



// Define "MyApp" as a revealing module

MyApp = (function(Backbone, $){

  var View = Backbone.View.extend({
    // do stuff here  
  });

  return {
    init: function(){
      var view = new View();
      $("#some-div").html(view.render().el);
    }
  };

})(Backbone, jQuery);



// Run "MyApp" in DOMReady

$(function(){
  MyApp.init();
});

1
ขอบคุณสำหรับคำตอบโดยละเอียดนี้ ฉันรู้เกี่ยวกับฟังก์ชัน DOMReady จะโทรเมื่อเหตุการณ์ที่พร้อมใช้งาน DOM เริ่มทำงานเท่านั้น แต่ไม่เคยคิดว่าจะเป็นปัญหา การแยกรหัสเพื่อกำหนดบิตกระดูกสันหลังภายในโมดูลจากนั้นการโต้ตอบกับพวกเขาใน Dom ready ดูเหมือนจะเป็นแนวทางที่ดีที่สุด
Matt Roberts

2
ที่น่าสนใจคือแอพตัวอย่าง "สิ่งที่ต้องทำ" ที่มี backbone src ทำให้ทุกอย่างในโดมพร้อม
Matt Roberts

2
อย่าลืมรูปแบบโมดูลจาวาสคริปต์เรียกอีกอย่างว่าIIFEไฟล์.
Jess

1
ฟังก์ชั่นที่ไม่ระบุชื่อจะถูกเรียกใช้เป็นหลักในเวลาเดียวกับที่ DOM พร้อมแล้วมันจะทำให้มีประสิทธิภาพมากขึ้นได้อย่างไร
bhavya_w

14

ในฐานะที่เป็นเครื่องหมายเล็กน้อยการส่ง $ เป็นอาร์กิวเมนต์ไปยังฟังก์ชันที่ไม่ระบุตัวตนทำให้ $ local ไปยังฟังก์ชันนั้นซึ่งมีผลกระทบเชิงบวกเล็กน้อยหากฟังก์ชัน $ ถูกเรียกใช้มาก เนื่องจาก javascript จะค้นหาขอบเขตโลคัลสำหรับตัวแปรก่อนจากนั้นจึงลัดเลาะลงไปจนถึงขอบหน้าต่าง (โดยที่ $ มักจะอยู่)


9

ช่วยให้มั่นใจได้ว่าคุณสามารถใช้ภายในที่ปิดได้ตลอดเวลา$แม้ว่าจะ$.noConflict()ใช้แล้วก็ตาม

หากไม่มีการปิดนี้คุณควรใช้jQueryแทน$ตลอดเวลา


4

เป็นการหลีกเลี่ยงความขัดแย้งที่อาจเกิดขึ้นของตัวแปร $ หากมีอย่างอื่นกำหนดตัวแปรชื่อ $ ปลั๊กอินของคุณอาจใช้คำจำกัดความที่ไม่ถูกต้อง

อ้างอิงhttp://docs.jquery.com/Plugins/Authoring#Getting_Startedสำหรับรายละเอียดเพิ่มเติม


2

ใช้ทั้งสองอย่าง

ฟังก์ชันเรียกใช้งานด้วยตนเองที่คุณส่งผ่านใน jQuery เพื่อป้องกันความขัดแย้งของไลบรารีและเพื่อให้แน่ใจว่า jQuery พร้อมใช้งานตามที่คุณคาดหวังด้วย $

และวิธีทางลัด. พร้อม () ตามที่จำเป็นเพื่อเรียกใช้จาวาสคริปต์หลังจากโหลด DOM แล้วเท่านั้น:

(function($) {
    $(function(){
          //add code here that needs to wait for page to be loaded
    });

    //and rest of code here
})(jQuery);

เวอร์ชันที่สั้นกว่าที่ฉันพบที่อื่นใน SO (ยังป้องกันไม่ได้กำหนด) :jQuery(function ($, undefined) { /* Code */ });
Jared Gotte
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.