การปิดตัวเองโดยไม่ระบุชื่ออ้างอิงตนเอง: JavaScript ไม่สมบูรณ์หรือไม่


18

ความจริงที่ว่าการปิดฟังก์ชั่นอ้างอิงตัวตนที่ไม่ระบุชื่อนั้นเป็นสิ่งสำคัญใน JavaScript แนะนำว่า JavaScript เป็นข้อกำหนดที่ไม่สมบูรณ์หรือไม่ เราเห็นสิ่งนี้มาก:

(function () { /* do cool stuff */ })();

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

เปรียบเทียบกับ ActionScript 3 ซึ่งอิงจาก ECMAScript ซึ่งคุณจะได้รับ

package com.tomauger {
  import bar;
  class Foo {
     public function Foo(){
       // etc...
     }

     public function show(){
       // show stuff
     }

     public function hide(){
       // hide stuff
     }
     // etc...
  }
}

ตรงกันข้ามกับ convolutions ที่เราดำเนินการใน JavaScript (สิ่งนี้จากเอกสารการเขียนปลั๊กอิน jQuery ):

(function( $ ){

  var methods = {
    init : function( options ) { // THIS },
    show : function( ) { // IS   },
    hide : function( ) { // GOOD },
    update : function( content ) { // !!! }
  };

  $.fn.tooltip = function( method ) {

    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    

  };

})( jQuery );

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


22
"JavaScript ไม่สามารถใช้ ... คลาสที่เหมาะสมหรือไม่" ไม่มันมีต้นแบบที่เหมาะสมแล้ว ต้นแบบไม่ได้ด้อยกว่าคลาส พวกเขาแตกต่าง. ผู้คนได้ลองเพิ่มคลาสใน JavaScript ในเวลาต่างๆและค่อนข้างประสบความสำเร็จ
Rein Henrichs

5
@Rein: และ ActionScript แต่อย่างใดการจัดการมัน ...
เมสันล้อ

8
@Tom ไม่มี "คลาสในตัว" ไม่มีสิ่งดังกล่าวเป็นชั้นอยู่ในภาษา prototypal คุณทำให้กระบวนทัศน์ทั้งสองเป็นไปอย่างต่อเนื่อง
Rein Henrichs

1
ฉันเองพบว่าคุณสมบัติภาษาฟังก์ชันที่ไม่ระบุชื่อมีความยืดหยุ่นมากกว่าคลาส อย่างไรก็ตามฉันชอบโปรแกรมที่ใช้งานได้ซึ่งสำนวนนี้เป็นเรื่องธรรมดา
dietbuddha

1
สำหรับคนอื่น ๆ ที่นี่: brianodell.net/?page_id=516เป็นไพรเมอร์ที่ยอดเยี่ยมเกี่ยวกับ JavaScript เป็นภาษาต้นแบบ
Tom Auger

คำตอบ:


9

ฉันคิดว่าทุกอย่างเป็นเรื่องของการลิ้มรส แต่นี่ไม่เหมือน kludge เมื่อคุณต้องการเนมสเปซส่วนตัว JavaScript ไม่สามารถใช้แพ็คเกจและคลาสที่เหมาะสมได้ใช่หรือไม่

ความคิดเห็นส่วนใหญ่มีการโต้เถียงกับตำนานที่ว่า "ต้นแบบเป็นคลาสของชายยากจน" ดังนั้นฉันจะทำซ้ำว่า OO ที่ใช้ต้นแบบไม่ได้ด้อยกว่าในทางใดทางกับ OO ตามระดับ

อีกจุดหนึ่ง "kludge เมื่อคุณต้องการเนมสเปซส่วนตัว" คุณอาจประหลาดใจที่รู้ว่าโครงการใช้กากตะกอนที่แน่นอนเพื่อกำหนดขอบเขต นั่นไม่ได้หยุดจากการเป็นตัวอย่างตามแบบฉบับของการกำหนดขอบเขตคำศัพท์ที่ทำได้ดี

แน่นอนใน Scheme 'kludge' ถูกซ่อนอยู่หลังมาโคร ....


1
คุณไม่พบหลักฐานใด ๆ ในการสำรองการยืนยันของคุณว่า Scheme เป็นตัวอย่างหลักของการกำหนดขอบเขตคำศัพท์ที่ทำได้ดีหรือสิ่งนี้เกี่ยวข้องกับวิธีที่ Scheme ใช้ฟังก์ชันเพื่อกำหนดขอบเขต
DeadMG

ไม่สามารถพูดกับ Scheme ได้ว่าเป็นแบบอย่าง แต่ตัวอย่างหนึ่งของผู้ร่วมสร้าง JS Brendan Eich พูดคุย Scheme มีบทบาทในการออกแบบของ JS ที่นี่: readwrite.com/2011/07/22/javascript-was-no-accident
Erik Reppen

7

ก่อนอื่นสิ่งที่สอง:

  1. อีกวิธีหนึ่งในการดู JavaScript คือ 1 ล้านและ 1 สิ่งที่คุณสามารถทำได้ด้วยฟังก์ชันเป็นโครงสร้าง มันคือทั้งหมดที่มีถ้าคุณมองหามัน มันไม่เคยห่างไกลจากฟังก์ชั่น

  2. สิ่งที่เขียนในปลั๊กอิน jQuery นั้นแย่มาก ฉันไม่รู้ว่าทำไมพวกเขาถึงสนับสนุนเรื่องนี้ $ ส่วนขยายควรเป็นสิ่งที่ใช้งานทั่วไปที่ $ มีวิธีการที่ครอบคลุมดีไม่ใช่วิธีการ build-me-a-complete-widget มันเป็นเครื่องมือปรับสภาพ DOM-API การใช้งานถูกฝังไว้ในวัตถุของคุณเองอย่างดีที่สุด ฉันไม่เห็นความสนใจที่จะใช้มันเป็นที่เก็บไลบรารี UI แบบเต็ม

แพ็คเกจบนเว็บไซด์ของลูกค้านั้นไร้ประโยชน์

สิ่งที่ฉันไม่ชอบเป็นการส่วนตัวเกี่ยวกับแพ็คเกจบนเว็บฝั่งไคลเอ็นต์ก็คือเรามักจะแกล้งทำเป็นว่าเรากำลังทำอะไรบางอย่างที่ไม่จริง ในเว็บโพสต์. NET และ gobs-of-horrifying-stuff-that-never-panned-out- จาก --- เพื่อน Java โลกของเราฉันควรคิดถึง HTML ขนาดใหญ่ที่มีทรัพยากรที่เชื่อมโยงเป็นสิ่งที่มันเป็นจริง และอย่าพยายามเอาใจนักพัฒนาแอประบบปฏิบัติการที่เรียนรู้สิ่งใหม่โดยการแสร้งทำเป็นเรื่องอื่น ใน JS บนเว็บฝั่งไคลเอ็นต์ไม่มีสิ่งใดได้รับการ "นำเข้า" ยกเว้นการทำสิ่งที่น่ากลัวกับ Ajax ที่ทำงานโดยไม่รู้การแคชของเบราว์เซอร์ซึ่งใช่มีหลายคนพยายามทำ สิ่งที่สำคัญสำหรับเบราว์เซอร์ก็คือมันถูกโหลดและตีความหรือไม่ เราไม่ได้ซ่อนโค้ดไว้บนไคลเอนต์ใด ๆ ให้ใช้งานได้ "ในกรณี" ด้วยเหตุผลที่ดี # 1 การที่ฉันเพิ่งอธิบายการพึ่งพาปลั๊กอินและเบราว์เซอร์ปลั๊กอินสำหรับเว็บแอปเนื่องจากปรากฏการณ์ไม่ได้ผลดีเกินไป เราต้องการเว็บในขณะนี้ ไม่ใช่หลังจาก Adobe หรือ Sun อัปเดตเป็นครั้งที่สามในสัปดาห์นี้

ภาษามีสิ่งที่ต้องการสำหรับโครงสร้าง

วัตถุ JS ไม่แน่นอนสูง เราสามารถแยกต้นไม้ของเนมสเปซออกได้ในระดับใดก็ตามที่เราเห็นว่ามีประโยชน์ในการทำเช่นนั้นและมันง่ายมากที่จะทำ แต่ใช่สำหรับทุกสิ่งที่สามารถนำกลับมาใช้ใหม่ได้คุณจะต้องติดรูทของไลบรารีใด ๆ ในพื้นที่ส่วนกลาง การอ้างอิงทั้งหมดเชื่อมโยงและโหลดพร้อมกันดังนั้นอะไรคือจุดประสงค์ของการทำสิ่งอื่น จุดประสงค์ในการหลีกเลี่ยงเนมสเปซส่วนกลางไม่ใช่สิ่งใดที่เลวร้าย มันเป็นสิ่งที่มากเกินไปที่มีไม่ดีเพราะคุณเสี่ยงต่อการชนของเนมสเปซหรือเขียนทับคุณสมบัติของภาษาหลักโดยไม่ตั้งใจ

เพียงเพราะมันเป็นที่นิยมไม่ได้หมายความว่าเราทำถูกแล้ว

ตอนนี้เมื่อคุณเห็นสิ่งนี้ทั่วเว็บแอปฝั่งไคลเอ็นต์:

(function(){
//lots of functions defined and fired and statement code here
})()

ปัญหาไม่ใช่ว่าเราไม่มีเครื่องมือในการจัดโครงสร้างแอปปัญหาคือคนไม่ได้ให้ความสำคัญกับโครงสร้าง สำหรับไซต์ที่ถูกทิ้งชั่วคราวชั่วคราวสัก 2-3 หน้าที่หน่วยงานออกแบบฉันไม่มีปัญหากับเรื่องนั้น ที่ที่มันน่าเกลียดก็คือเมื่อคุณต้องสร้างบางสิ่งบางอย่างที่บำรุงรักษาได้และชัดเจนและง่ายต่อการปรับเปลี่ยน

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

แต่มีการใช้งาน JS ด้วยแพ็คเกจ / โมดูล

โปรดจำไว้ว่าใน Node.js ที่สิ่งต่าง ๆ เหล่านี้มีเหตุผลมากขึ้นพวกเขามีโมดูล JS โดยสมมติว่าเราสามารถหลีกเลี่ยง uber-config-hell ที่ทำให้เกิดภัยพิบัติในภาษาอื่นเป็นสิ่งเดียวในสมการและไฟล์ที่เรียกใช้แต่ละไฟล์นั้นมีขอบเขตแยกต่างหาก แต่บนหน้าเว็บการเชื่อมโยงไฟล์ js เป็นคำสั่งนำเข้า การทำการนำเข้าได้มากขึ้นเป็นเพียงการเสียเวลาและทรัพยากรเนื่องจากการได้รับทรัพยากรต้องการความพยายามมากกว่าเพียงแค่เพิ่มลิงก์ไปยังไฟล์ตามที่คุณต้องการเพราะรู้ว่าพวกเขาจะถูกแคชในเบราว์เซอร์หากหน้าอื่นต้องการอีกครั้ง ดังนั้นพยายามแยกพื้นที่ส่วนกลางโดยการทำสิ่งอื่นนอกเหนือจากการสร้างโรงงานอแด็ปเตอร์วัตถุเช่น jQuery หรือวัตถุแบบดั้งเดิมที่ครอบคลุมชุดย่อยขนาดใหญ่ของงานในโดเมนที่กำหนดในขณะที่ครอบครองจุดหนึ่งในโลก มี'http://wiki.ecmascript.org/doku.php?id=harmony:modules

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

อย่างไรก็ตามความจริงที่ว่าเราสามารถทำสิ่งนั้นได้นั้นยอดเยี่ยมมาก การใช้งานจำนวนมากเป็นสัญญาณว่าผู้พัฒนา JS ยังคงเติบโตเต็มที่ แต่มันไม่ใช่ช่องโหว่ในภาษาสำหรับใครก็ตามที่ไม่ได้พยายามบังคับกระบวนทัศน์เข้าสู่เว็บฝั่งไคลเอ็นต์ที่ไม่เหมาะสม


สำหรับผู้ลงคะแนนเสียงคุณช่วยอธิบายได้ไหม เมื่อมีคนเขียนว่าฉันคิดว่าเขาสมควรได้รับคำอธิบาย!
Songo

+1 คำตอบที่ดีไม่แน่ใจว่าทำไมการลงคะแนนก่อน
ชม

บทความและมุมมองที่ยอดเยี่ยม ฉันชอบ "เพียงเพราะมันเป็น trope ไม่ได้หมายความว่าถูกต้อง" ฉันคิดว่าปัญหาของฉันคือฉันรู้สึกสะดวกสบายกับภาษาที่เข้มงวดซึ่ง (IMO) ช่วยพัฒนาประสิทธิภาพได้หลายวิธี จาวาสคริปต์ดูเหมือนจะขัดใจจริงๆที่ไม่มีการตรวจสอบและยอดคงเหลือในตัวจำนวนมาก: คุณสามารถทำสิ่งที่คุณต้องการได้ดังนั้นภูมิทัศน์ที่ออกมามีความยุ่งเหยิงของสำนวนและการปฏิบัติ เป็นการยากที่จะตอกตะปูวิธี "ถูกต้อง" เพื่อเข้าถึงโครงสร้างการเข้ารหัสของคุณ แม้ว่าฉันจะยอมรับว่าสำหรับการสมัครงานด่วน 1 ครั้ง แต่นี่ไม่ใช่เรื่องใหญ่
Tom Auger

1
IMO มีหลายสิ่งที่คุณสามารถทำได้ด้วยเชือกมากมายนอกเหนือจากการแขวนคอตัวเองและคุณเรียนรู้ที่จะเขียนโค้ดที่มีประสิทธิภาพเร็วขึ้นจากการแขวนด้วยตัวเองเป็นครั้งคราวซึ่งเกิดขึ้นไม่บ่อยนักในขณะที่คุณพัฒนานิสัยที่ดีขึ้น ทุกคนหรือผู้สมัครที่เหมาะสมที่สุดสำหรับทุกงาน ฉันสงสัยว่ายิ่งคุณเรียนรู้เกี่ยวกับมันมากเท่าไหร่คุณก็จะยิ่งอดทนได้มากขึ้นเท่านั้น ฉันรู้สึกเหมือนขาดสมองครึ่งเมื่อพยายามทำสิ่งต่าง ๆ ในภาษาที่ไม่มีฟังก์ชั่นชั้นเรียนหรือวัตถุที่ยืดหยุ่น / เปลี่ยนแปลงได้เหมือน JS
Erik Reppen

4

สิ่งอื่นที่คุณขาดหายไปก็คือ javscript จะต้องใช้งานร่วมกันได้ หากคุณพยายามที่จะแนะนำรูปแบบของแพคเกจมันอาจทำลายเว็บได้อย่างบ้าคลั่ง นั่นจะไม่ดี! Doug Crockford ได้พูดคุยเกี่ยวกับเรื่องนี้ในหลาย ๆ จุดและทำไมความพยายามที่จะเพิ่มมันล้มเหลว


นั่นเป็นจุดที่ดี และยัง ActionScript จัดการมันโดยเพียงแค่วางเวอร์ชั่นใหม่ เมื่อกำหนดแท็กสคริปต์ของคุณคุณจะสามารถระบุเวอร์ชัน JavaScript ได้เสมอดังนั้นการ "ทำลาย" ไซต์ที่มีอยู่ควรไม่ใช่ปัญหา
Tom Auger

1
ในทางปฏิบัติแท็กสคริปต์ส่วนใหญ่ในเน็ตไม่มีหมายเลขเวอร์ชัน บอกตามตรงฉันไม่แน่ใจเกี่ยวกับปัญหาทั้งหมดในอันนี้ แต่ฉันรู้ว่าคนที่คิดเกี่ยวกับสิ่งนี้ได้ตัดสินใจว่ามันไม่สามารถทำได้
Zachary K

1
@Tom: Adobe ยังควบคุมแพลตฟอร์ม Flash ได้อย่างสมบูรณ์ ไม่มีบุคคลใดสามารถควบคุมแพลตฟอร์ม JS ทั้งหมดได้อย่างเต็มที่ นอกจากนี้การตรึงหมายเลขเวอร์ชันสำหรับสคริปต์ JS ในเบราว์เซอร์ก็หมายความว่าคุณไม่สนับสนุนเบราว์เซอร์รุ่นเก่าหรือต้องเขียนสคริปต์สองตัว ดังนั้นจึงเป็นปัญหา
Jeremy Heiler

2

ใช่มันเป็นกระบอง

ผู้คนมากมายพูดว่า "ต้นแบบไม่ด้อยกว่าคลาส" ฉันไม่เห็นด้วย แต่นั่นเป็นเรื่องของการตั้งค่า แต่นั่นไม่ใช่แม้แต่ปัญหาที่แท้จริงของ JavaScript แต่ปัญหาก็คือมันถูกออกแบบมาเป็นภาษาสคริปต์ที่รวดเร็วและสกปรกสำหรับการทำสิ่งต่าง ๆ เช่นปุ่มภาพเคลื่อนไหว ย้อนกลับไปในช่วงกลางยุค 90 ไม่มีใครเคยคิดว่า JavaScript จะถูกขอให้ทำบางสิ่งที่บ้าคลั่งที่มันทำอยู่ตอนนี้


6
ฉันไม่เห็นด้วย JavaScript เป็นภาษาที่ยอดเยี่ยมจริงๆ ว่ามันถูกรวมเข้าด้วยกันกับ DOM ที่ระบุและไม่เข้ากันซึ่งกันและกันเป็นที่ที่ปัญหาทั้งหมดเริ่มต้นขึ้น
Dean Harding

2
สิ่งนี้เกี่ยวข้องกับต้นแบบอย่างไร
Erik Reppen

2

ฟังก์ชั่นการเรียกตนเองที่ไม่ระบุชื่อนั้นคล้ายกับโมดูลมากกว่าคลาส เป็นเรื่องน่ารำคาญที่ค่าเริ่มต้นสำหรับ javascript นั้นจะทำงานในขอบเขตส่วนกลาง คณะกรรมการที่ทำงานกับ JS.next กำลังพิจารณาที่จะเพิ่มโมดูลอย่างจริงจังเพื่อที่คุณจะไม่ปล่อยตัวแปรในเครื่องของคุณให้อยู่ในขอบเขตส่วนกลาง โชคดีที่ฟังก์ชั่นของ Javascript นั้นมีความหมายที่สะดวกสบายเช่นนี้ซึ่งเราสามารถใช้ฟังก์ชั่นที่ไม่ระบุชื่อเป็นขอบเขตส่วนตัวได้อย่างง่ายดาย

ฉันไม่เห็นว่าชั้นเรียนมีส่วนร่วมในการอภิปรายอย่างไรจริง ๆ ยกเว้นว่าพวกเขาเป็นโครงสร้างการกำหนดขอบเขตระดับบนสุดในหลายภาษา โมดูล / แพ็กเกจที่ดีขึ้น / โปรดให้ฉัน -a-local-scope-so-i- อย่าปล่อยให้ตัวแปรของฉันในสภาพแวดล้อมทั่วโลกจะดีมากที่จะมี


1

คุณอาจต้องการดู ExtJS 3 และ 4 ที่พวกเขาจัดการเพื่อใช้เนมสเปซได้ค่อนข้างดี

- เพิ่มหลังจาก -1

จุดของฉันที่นี่เป็นไปได้ที่จะซ่อน 'convolutions' เหล่านี้ทั้งหมดและยังคงมีรหัสที่ค่อนข้างเป็นมิตรเช่น:

Ext.ns('com.tomauger');
Ext.Loader.load('bar.js'); //unfortunately filname needs to be used
MyNameSpace.Foo = {
   //...
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.