เหตุใดการปิด JavaScript จึงสำคัญสำหรับ JavaScript


16

การแสดงออกแลมบ์ดาของ C # ก็มีการปิดเช่นกันแต่ไม่ค่อยมีการพูดคุยกันโดยชุมชนหรือหนังสือ C # ฉันเห็นคน JavaScript และหนังสือพูดถึงการปิดตัวมันมากกว่าที่พวกเขาทำในโลก C # ทำไมถึงเป็นอย่างนั้น?


3
เพราะจาวาสคริปต์นั้นถือว่าเป็นภาษาสำหรับการทำงานระดับเฟิร์สคลาสและ C # เป็น OOP คลาสสิก รูปแบบการเขียนโปรแกรมที่แตกต่างกัน
Raynos

1
การมีฟังก์ชั่นชั้นหนึ่งทำให้ภาษาเป็นภาษาของฟังก์ชัน PHP (ตั้งแต่ 5.3), python หรือ D มีฟังก์ชันชั้นหนึ่ง คุณจะบอกว่าเป็นภาษาที่ใช้งานได้หรือไม่? ไม่แน่นอนและ javascript เช่นกัน
deadalnix

1
@deadalnix JavaScript เป็นภาษาแบบหลายกระบวนทัศน์ ส่วนใหญ่สนับสนุนกระบวนทัศน์การทำงานและต้นแบบ OO มันเป็นโดยไม่มีหมายถึงบริสุทธิ์ภาษาทำงาน แต่คุณสามารถเขียน JavaScript ในกระบวนทัศน์การทำงานโดยไม่ต้องดัดภาษา ฉันจะพูดเหมือนกันของ C # และหลาม
Raynos

3
@deadalnix ภาษาที่ให้คุณกำหนด Y-combinator เป็นภาษาที่ใช้งานได้ ตามคำจำกัดความ
SK-logic

1
@deadalnix: ฉันคิดว่าสิ่งที่เกิดขึ้นคือคำถามว่าแนวทางการส่งเสริมภาษา มีเฟรมเวิร์กและแพลตฟอร์ม JavaScript มากมาย (โดยเฉพาะอย่างยิ่ง node.js และ DOM (โมเดลเหตุการณ์)) ที่ต้องพึ่งพาฟังก์ชั่นการสั่งซื้อครั้งแรก PHP มีคุณสมบัติที่อนุญาตให้ใช้รูปแบบการเขียนโปรแกรมเหมือนกัน แต่ถ้าคุณดู API มาตรฐานหรือเฟรมเวิร์กจำนวนมากคุณจะเห็นว่ามันไม่ได้เป็นแกนหลักของภาษา
back2dos

คำตอบ:


5

เพราะจาวาสคริปต์ไม่มีคุณสมบัติอย่างเนมสเปซและคุณสามารถเลอะเทอะได้อย่างง่ายดายด้วยการจัดเรียงวัตถุทั่วโลก

ดังนั้นจึงเป็นสิ่งสำคัญที่จะสามารถแยกรหัสบางอย่างในสภาพแวดล้อมการดำเนินการของตัวเอง การปิดนั้นสมบูรณ์แบบสำหรับสิ่งนั้น

การใช้งานการปิดนี้ไม่สมเหตุสมผลในภาษาเช่น C # ที่คุณมีเนมสเปซ, คลาสและอื่น ๆ เพื่อแยกรหัสและไม่ใส่ทุกอย่างในขอบเขตส่วนกลาง

หลักปฏิบัติทั่วไปสำหรับรหัสจาวาสคริปต์คือเขียนแบบนี้:

(function(){
    // Some code
})();

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

Javascript เป็นภาษาที่แตกต่างจาก C # มาก มันไม่ใช่แบบเชิงวัตถุมันเป็นแบบต้นแบบ สิ่งนี้นำไปสู่การปฏิบัติที่แตกต่างกันมากในตอนท้าย

อย่างไรก็ตามการปิดเป็นสิ่งที่ดีดังนั้นใช้งานได้แม้ใน C #!

แก้ไข: หลังจากหารือเกี่ยวกับการแชทของ stackoverflow ฉันคิดว่า anwer นี้ต้องได้รับการพิจารณา

ฟังก์ชั่นในรหัสตัวอย่างไม่ได้เป็นการปิด อย่างไรก็ตาม fucntion นี้สามารถกำหนดตัวแปรท้องถิ่นและฟังก์ชั่นที่ซ้อนกัน ฟังก์ชันที่ซ้อนกันทั้งหมดที่ใช้ตัวแปรโลคัลเหล่านี้เป็นการปิด

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

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

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


9
นั่นไม่ใช่การปิด คุณอธิบายถึงข้อดีของการใช้ฟังก์ชั่นเพื่อสร้างขอบเขตภายใน
Raynos

2
การปิดเป็นเพียงการปิดถ้ามันปิดมากกว่าตัวแปรอิสระ นอกจากนี้ขอขอบคุณสำหรับการบอกฉันฉันไม่ทราบวิธีการทำงานของ JavaScript :)
Raynos

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

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

2
-1 เช่นกัน สิ่งนี้ไม่ได้อธิบายถึงการปิดมันอธิบายถึงขอบเขต
Izkata

12

อาจเป็นเพราะการใช้งานการวางแนววัตถุที่เป็นที่นิยมของ JavaScript ขึ้นอยู่กับการปิด ลองดูตัวอย่างง่ายๆ:

function counter() {
   var value = 0;
   this.getValue = function() { return value; }
   this.increase = function() { value++; }
}

var myCounter = new counter();
console.log(myCounter.getValue());
myCounter.increase();
console.log(myCounter.getValue());

วิธีการgetValueและอยู่ในการปิดความเป็นจริงห่อหุ้มเซลล์แสงอาทิตย์ตัวแปรincreasevalue


3
-1 "ขึ้นอยู่กับการปิด" นั่นเป็นอัตวิสัยสูง มันไม่ใช่.
Raynos

Raynos: สนใจที่จะแสดงให้เราเห็นถึงวิธีการสร้างและใช้สมาชิกส่วนตัวโดยไม่ต้องปิด?
281377

1
@ammoQ ไม่มีสิ่งใดเป็นส่วนตัวใน JavaScript สิ่งที่คุณหมายถึงคือ "เพราะการจำลอง OO แบบดั้งเดิมของ JavaScript ขึ้นอยู่กับการปิด" JavaScript OO นั้นเป็นต้นแบบซึ่งเป็นกระบวนทัศน์ที่แตกต่าง มันเป็นคำตอบที่ดีสำหรับคำถามที่ว่า "เราใช้การปิดใน JavaScript เพราะมีความจำเป็นที่จะเลียนแบบ OO คลาสสิก"
Raynos

1
@keppla ฉันหมายถึง "OO ขึ้นอยู่กับการปิด" เป็นเรื่องส่วนตัว คุณไม่จำเป็นต้องปิดเพื่อ OO เลย
Raynos

2
คุณกำลังแสดงให้ฉันเห็นในฐานะตัวแทน
ผู้หญิง

4

เพราะห้องสมุดหลายแห่งที่ทำให้จาวาสคริปต์ใช้งานได้

ลองดูที่JQuery , PrototypeหรือMooToolsเพียงเพื่อชื่อสามยอดนิยม แต่ละไลบรารีเหล่านั้นจัดเตรียมeachวิธีสำหรับการรวบรวมเป็นวิธีการทำซ้ำที่ต้องการซึ่งใช้ฟังก์ชันตัววนซ้ำ ฟังก์ชั่นนั้นเมื่อเข้าถึงค่าในขอบเขตด้านนอกจะเป็นการปิด:

[1,2,3].each(function(item) {
   console.log(item);
});

และมันก็ไม่ได้หยุดอยู่แค่นั้น: การเรียกกลับใน Ajax การจัดการเหตุการณ์ใน Ext.js และอื่น ๆ ล้วน แต่มีฟังก์ชั่นและถ้าคุณไม่ต้องการที่จะขยายโค้ดของคุณด้วยฟังก์ชั่น 100 ส่วนที่เรียกว่าหนึ่งครั้ง


1
ทำไมมันไม่ปิดตัวลง? console.logถูกกำหนดในขอบเขตด้านนอกดังนั้นจึงconsoleเป็น 'ตัวแปรอิสระ' และทำไมเป็นผลให้ for-loop ซึ่งไม่มีอะไรแตกต่างออกไป
keppla

@ Raynos: คำจำกัดความของการปิดของฉันคือ 'บล็อกที่มีตัวแปรอิสระ' มันไม่ได้ทำให้สถานะนั้นหลวมตัวแปรอิสระที่เกิดขึ้นจะอยู่ในขอบเขตด้านบน แต่เพื่อสนับสนุนจุดของฉันพิจารณาวิธีการนี้: pastie.org/2144689 ทำไมสิ่งนี้ถึงไม่ดี?
keppla

ฉันยังคิดว่าการ "ปิด" เหนือข้อมูลทั่วโลกถือเป็นการโกง ฉันยอมรับว่าการเข้าถึงข้อมูลในขอบเขตขอบเขตนั้นเป็นเรื่องง่ายมันเป็นแนวทางปฏิบัติที่ดีในการลดการเข้าถึงให้น้อยที่สุด
Raynos

ตกลงการลดการเข้าถึง
keppla

ควรสังเกตว่าด้วยตัววนซ้ำอาเรย์ (forEach, map, ลดและอื่น ๆ ) ไม่มีเหตุผลที่จะปิดพวกเขามีสถานะทั้งหมดที่ส่งผ่านโดยตรง ฉันคิดว่ามันเป็นรูปแบบการต่อต้านสำหรับพวกเขาที่จะปิด
Raynos

3

ฉันเห็นด้วยกับคำตอบอื่น ๆ ที่การเข้ารหัส "ดี" กับ JavaScript นั้นขึ้นอยู่กับการปิด อย่างไรก็ตามนอกเหนือจากนั้นอาจเป็นเพียงคำถามว่าคุณลักษณะแต่ละรายการมีความยาวเท่าใดในแต่ละภาษา JavaScript นั้นมีการปิดโดยทั่วไปนับตั้งแต่มีการใช้งานครั้งแรก ในทางตรงกันข้าม C # มีเพียงพวกเขาตั้งแต่ 3.0 ซึ่งเผยแพร่กับ Visual Studio 2008

โปรแกรมเมอร์ C # ที่ฉันพบจำนวนมากยังคงทำงานในโครงการ 2.0 และแม้ว่าพวกเขาจะทำงานใน 3.0 หรือ 4.0 พวกเขามักจะยังคงใช้สำนวน 2.0 ฉันรักการปิด หวังว่าพวกเขาจะใช้กันอย่างแพร่หลายใน C # เนื่องจากแนวคิดเผยแพร่ในหมู่นักพัฒนา C #


2

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

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


1
การพิมพ์สแตติกต้องทำอะไรกับสิ่งนี้ การปิดเป็นมุมฉาก

-1

เหตุผลหนึ่งที่ฉันต้องเรียนรู้เกี่ยวกับพวกเขาก็เพราะว่าเมื่อคุณวนลูปผ่านองค์ประกอบ DOM (หรืออะไรก็ตามจริงๆ) คุณต้องการที่จะสามารถ "ปิด" หรือ "ห่อหุ้ม" ขอบเขตตัวแปร ดังในตัวอย่างที่โพสต์ที่นี่: /programming/5606059/how-to-create-closure-in-loop-and-store-it-in-variable-for-later-execution

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