JavaScript เป็นหนึ่งในภาษาการเขียนโปรแกรมที่ใช้บ่อยที่สุดในโลก มันเป็นภาษาทั่วไปในเว็บโลกและใช้โดยเบราว์เซอร์ทั้งหมด การกำเนิดของ JavaScript กลับไปสู่ยุคของ Netscape และเนื้อหาหลักได้รับการพัฒนาอย่างเร่งรีบเพื่อต่อสู้กับ Microsoft และเข้าร่วมในสงครามเบราว์เซอร์ที่ดุเดือดในเวลานั้น เนื่องจากการเปิดตัวก่อนกำหนดคุณสมบัติที่น่าสงสารบางอย่างก็ส่งผลอย่างหลีกเลี่ยงไม่ได้
แม้ว่าเวลาในการพัฒนาจะสั้น JavaScript ยังคงมีคุณสมบัติที่ทรงพลังมากมายยกเว้นคุณสมบัติของการแบ่งปันเนมสเปซทั่วโลกสำหรับแต่ละสคริปต์
เมื่อเว็บเพจถูกโหลดด้วยรหัส JavaScript มันจะถูกฉีดเข้าไปในเนมสเปซทั่วโลกและจะแบ่งปันพื้นที่ที่อยู่เดียวกันกับสคริปต์ที่โหลดอื่น ๆ ทั้งหมดซึ่งจะนำไปสู่ปัญหาด้านความปลอดภัยความขัดแย้งและปัญหาทั่วไป
แต่โชคดีที่ Node ได้ตั้งค่าข้อมูลจำเพาะสำหรับ JavaScript ฝั่งเซิร์ฟเวอร์และยังใช้มาตรฐานโมดูล CommonJS ในมาตรฐานนี้แต่ละโมดูลมีบริบทของตัวเองและแตกต่างจากโมดูลอื่น ๆ ซึ่งหมายความว่าโมดูลจะไม่ก่อให้เกิดมลพิษในขอบเขตทั่วโลกเนื่องจากไม่มีขอบเขตที่เรียกว่าทั่วโลกเลยและโมดูลจะไม่รบกวนกันและกัน
ในบทนี้เราจะเรียนรู้เกี่ยวกับโมดูลที่แตกต่างกันหลายอย่างและวิธีการโหลด
การแยกรหัสออกเป็นชุดของโมดูลที่กำหนดไว้อย่างดีสามารถช่วยคุณควบคุมแอปพลิเคชันของคุณ ด้านล่างเราจะเรียนรู้วิธีการสร้างและใช้โมดูลของคุณเอง
เรียนรู้ว่าโหนดโหลดโมดูลอย่างไร
ในโหนดโมดูลสามารถอ้างอิงผ่านเส้นทางไฟล์หรือชื่อโมดูล หากโมดูลที่ไม่ใช่คอร์ถูกอ้างอิงตามชื่อโหนดจะรวมชื่อโมดูลไปยังเส้นทางไฟล์โมดูลที่เกี่ยวข้อง และโมดูลหลักเหล่านั้นที่มีฟังก์ชั่นหลักจะได้รับการโหลดล่วงหน้าเมื่อโหนดเริ่มต้น
โมดูลที่ไม่ใช่คอร์รวมถึงโมดูลบุคคลที่สามที่ติดตั้งโดยใช้ NPM (Node Package Manager) รวมถึงโมดูลท้องถิ่นที่สร้างโดยคุณหรือเพื่อนร่วมงานของคุณ
แต่ละโมดูลที่นำเข้าโดยสคริปต์ปัจจุบันจะแสดงชุดของ API ที่เปิดเผยไปยังโปรแกรมเมอร์ ก่อนที่จะใช้โมดูลคุณต้องใช้ฟังก์ชั่นที่ต้องการเพื่อนำเข้าเช่นนี้:
การคัดลอกรหัสมีดังนี้:
var module = reghed ('module_name')
รหัสด้านบนจะนำเข้าโมดูลชื่อ module_name อาจเป็นโมดูลหลักหรือโมดูลที่ติดตั้งด้วย NPM ฟังก์ชั่นที่ต้องการส่งคืนวัตถุที่มี API สาธารณะทั้งหมดของโมดูล ขึ้นอยู่กับโมดูลวัตถุที่ส่งคืนอาจเป็นค่า JavaScript ใด ๆ มันอาจเป็นฟังก์ชันหรือวัตถุที่มีชุดของแอตทริบิวต์ (ฟังก์ชั่น, อาร์เรย์หรือวัตถุ JavaScript ใด ๆ )
โมดูลส่งออก
ระบบโมดูล CommonJS เป็นวิธีเดียวที่จะแบ่งปันวัตถุและฟังก์ชั่นระหว่างไฟล์ภายใต้โหนด สำหรับโปรแกรมที่ซับซ้อนมากคุณควรสร้างคลาสวัตถุหรือฟังก์ชั่นใหม่ในชุดของโมดูลที่นำมาใช้ซ้ำได้อย่างดี สำหรับผู้ใช้โมดูลโมดูลจะเปิดเผยรหัสที่คุณระบุไว้ในโลกภายนอกเท่านั้น
ในตัวอย่างต่อไปนี้คุณจะเข้าใจว่าในโหนดไฟล์และโมดูลสอดคล้องกันทีละตัว เราสร้างไฟล์ที่เรียกว่า circle.js ซึ่งส่งออกตัวสร้างวงกลมไปด้านนอกเท่านั้น
การคัดลอกรหัสมีดังนี้:
วงกลมฟังก์ชัน (x, y, r) {
ฟังก์ชั่น r_squared () {
return math.pow (r, 2);
-
พื้นที่ฟังก์ชัน () {
return math.pi * r_squared ();
-
กลับ {พื้นที่: พื้นที่};
-
module.exports = Circle;
สิ่งที่สำคัญที่สุดในรหัสคือบรรทัดสุดท้ายซึ่งกำหนดสิ่งที่โมดูลส่งออกไปด้านนอก โมดูลเป็นตัวแปรพิเศษซึ่งแสดงถึงโมดูลปัจจุบันและโมดูลการส่งออกเป็นวัตถุที่ส่งออกจากโมดูล มันสามารถเป็นวัตถุใด ๆ ในตัวอย่างนี้เราส่งออกตัวสร้างวงกลมเพื่อให้ผู้ใช้โมดูลสามารถใช้โมดูลนี้เพื่อสร้างอินสแตนซ์วงกลม
นอกจากนี้คุณยังสามารถส่งออกวัตถุที่ซับซ้อนบางโมดูลการส่งออกเริ่มต้นเป็นวัตถุเปล่าและคุณส่งออกสิ่งที่คุณต้องการเปิดเผยไปยังโลกภายนอกเป็นคุณลักษณะของโมดูลวัตถุส่งออก ตัวอย่างเช่นคุณออกแบบโมดูลที่เปิดเผยชุดของฟังก์ชั่นไปด้านนอก:
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น printa () {
console.log ('a');
-
ฟังก์ชั่น printb () {
console.log ('B');
-
ฟังก์ชั่น printc () {
console.log ('c');
-
module.exports.printa = printa;
module.exports.printb = printb;
module.exports.pi = math.pi;
โมดูลนี้ส่งออกสองฟังก์ชั่น (printa และ printb) และหมายเลข (pi) และรหัสการโทรมีลักษณะเช่นนี้:
การคัดลอกรหัสมีดังนี้:
var mymodule2 = ต้องการ ('./ mymodule2');
mymodule2.printa (); // -> a
mymodule2.printb (); // -> b
console.log (mymodule2.pi); // -> 3.141592653589793
การโหลดโมดูล
ดังที่ได้กล่าวไว้ก่อนหน้านี้คุณสามารถใช้ฟังก์ชั่นที่ต้องการในการโหลดโมดูลและไม่ต้องกังวลว่าการโทรที่ต้องการในรหัสจะส่งผลกระทบต่อเนมสเปซทั่วโลกเนื่องจากไม่มีแนวคิดของ namespace ทั่วโลกในโหนด หากโมดูลมีอยู่โดยไม่มีข้อผิดพลาดในไวยากรณ์หรือการเริ่มต้นฟังก์ชันต้องการจะส่งคืนวัตถุโมดูลและคุณยังสามารถกำหนดวัตถุนี้ให้กับตัวแปรท้องถิ่นใด ๆ
มีหลายประเภทของโมดูลซึ่งสามารถแบ่งออกเป็นโมดูลหลักโมดูลท้องถิ่นและโมดูลบุคคลที่สามที่ติดตั้งผ่าน NPM ตามประเภทของโมดูลมีหลายวิธีในการอ้างถึงโมดูล มาเรียนรู้เกี่ยวกับความรู้เหล่านี้ด้านล่าง
กำลังโหลดโมดูลหลัก
โหนดมีโมดูลบางส่วนที่รวบรวมไว้ในไฟล์ไบนารีที่เรียกว่าโมดูลหลัก พวกเขาไม่สามารถอ้างอิงได้โดยเส้นทางและสามารถใช้กับชื่อโมดูลเท่านั้น โมดูลหลักมีลำดับความสำคัญในการโหลดสูงสุดและแม้ว่าจะมีโมดูลบุคคลที่สามอยู่แล้วในชื่อเดียวกันโมดูลหลักจะถูกโหลดก่อน
ตัวอย่างเช่นหากคุณต้องการโหลดและใช้โมดูล HTTP Core คุณสามารถทำได้:
การคัดลอกรหัสมีดังนี้:
var http = ต้องการ ('http');
สิ่งนี้จะส่งคืนวัตถุที่มีโมดูล HTTP ซึ่งมี APIs ของโมดูล HTTP เหล่านั้นที่กำหนดไว้ในเอกสารโหนด API
การโหลดโมดูลไฟล์
คุณยังสามารถใช้เส้นทางสัมบูรณ์เพื่อโหลดโมดูลจากระบบไฟล์:
การคัดลอกรหัสมีดังนี้:
var mymodule = ต้องการ ('/home/pedro/my_modules/my_module');
นอกจากนี้คุณยังสามารถใช้พา ธ สัมพัทธ์ตามไฟล์ปัจจุบัน:
การคัดลอกรหัสมีดังนี้:
var mymodule = ต้องการ ('../ my_modules/my_module');
var mymodule2 = ต้องการ ('./ lib/my_module_2');
ให้ความสนใจกับรหัสข้างต้น คุณสามารถละเว้นส่วนขยายของชื่อไฟล์ หาก Node ไม่สามารถค้นหาไฟล์นี้ได้คุณจะพยายามเพิ่ม JS ต่อท้ายเพื่อค้นหาอีกครั้งหลังจากชื่อไฟล์ (หมายเหตุของนักแปล: อันที่จริงนอกเหนือจาก JS คุณจะมองหา JSON และ Node สำหรับรายละเอียดคุณสามารถดูเอกสารเว็บไซต์อย่างเป็นทางการ) ดังนั้นหากไฟล์ที่เรียกว่า my_module.js มีอยู่ในไดเรกทอรีปัจจุบันจะมีวิธีการโหลดสองวิธี:
การคัดลอกรหัสมีดังนี้:
var mymodule = ต้องการ ('./ my_module');
var mymodule = reghed ('./ my_module.js');
การโหลดโมดูลไดเรกทอรี
คุณยังสามารถใช้เส้นทางไดเรกทอรีเพื่อโหลดโมดูล:
การคัดลอกรหัสมีดังนี้:
var mymodule = ต้องการ ('./ mymoduledir');
โหนดจะสมมติว่าไดเรกทอรีนี้เป็นแพ็คเกจโมดูลและพยายามค้นหาแพ็คเกจไฟล์นิยามแพ็คเกจแพ็คเกจ. json ในไดเรกทอรีนี้
หากไม่พบโหนดจะสมมติว่าจุดเริ่มต้นของแพ็คเกจคือไฟล์ index.js (หมายเหตุของนักแปล: นอกเหนือจาก index.js มันจะค้นหา index.node และไฟล์. node เป็นแพ็คเกจส่วนขยายไบนารีของ Node ดูเอกสารอย่างเป็นทางการสำหรับรายละเอียด) รหัสด้านบนเป็นตัวอย่าง โหนดจะพยายามค้นหาไฟล์./mymoduledir/index.js
ในทางตรงกันข้ามหากพบไฟล์ package.json โหนดจะพยายามแยกวิเคราะห์และค้นหาแอตทริบิวต์หลักในคำจำกัดความของแพ็คเกจจากนั้นใช้ค่าของแอตทริบิวต์หลักเป็นเส้นทางสัมพัทธ์ของจุดเข้า ในตัวอย่างนี้ถ้า package.json ถูกกำหนดดังนี้:
การคัดลอกรหัสมีดังนี้:
-
"ชื่อ": "mymodule",
"หลัก": "./lib/mymodule.js"
-
โหนดจะพยายามโหลดไฟล์./mymoduledir/lib/mymodule.js
โหลดจากไดเร็กทอรี node_modules
หากพารามิเตอร์ของฟังก์ชั่นต้องการไม่ใช่เส้นทางสัมพัทธ์หรือชื่อโมดูลหลักโหนดจะถูกค้นหาในไดเรกทอรีย่อย Node_Modules ของไดเรกทอรีปัจจุบัน ตัวอย่างเช่นในรหัสต่อไปนี้โหนดจะพยายามค้นหาไฟล์/node_modules/mymodule.js:
การคัดลอกรหัสมีดังนี้:
var mymodule = ต้องการ ('mymodule.js');
หากไม่พบโหนดจะยังคงค้นหาในโฟลเดอร์ Node_Modules ของไดเรกทอรีด้านบน หากไม่พบให้ค้นหาต่อในไดเรกทอรีด้านบนจนกว่าจะพบโมดูลที่เกี่ยวข้องหรือถึงไดเรกทอรีราก
คุณสามารถใช้คุณสมบัตินี้เพื่อจัดการเนื้อหาหรือโมดูลของไดเรกทอรี Node_Modules แต่เป็นการดีที่สุดที่จะมอบงานการจัดการโมดูลให้กับ NPM (ดูบทที่ 1) ไดเรกทอรี local node_modules เป็นตำแหน่งเริ่มต้นสำหรับโมดูลการติดตั้ง NPM การออกแบบนี้เชื่อมโยงโหนดและ NPM เข้าด้วยกัน โดยปกติแล้วในฐานะนักพัฒนาคุณไม่ต้องใส่ใจเกี่ยวกับคุณสมบัตินี้มากเกินไป คุณสามารถติดตั้งอัปเดตและลบแพ็คเกจโดยใช้ NPM ซึ่งจะช่วยให้คุณรักษาไดเรกทอรี Node_Modules
โมดูลแคช
โมดูลจะถูกแคชหลังจากการโหลดที่ประสบความสำเร็จครั้งแรกนั่นคือถ้าชื่อโมดูลได้รับการแก้ไขในเส้นทางไฟล์เดียวกันการเรียกทุกครั้งที่ต้องการ ('mymodule') จะส่งคืนโมดูลเดียวกัน
ตัวอย่างเช่นมีโมดูลที่เรียกว่า my_module.js ที่มีเนื้อหาต่อไปนี้:
การคัดลอกรหัสมีดังนี้:
console.log ('โมดูล my_module เริ่มต้น ... ');
module.exports = function () {
console.log ('สวัสดี!');
-
console.log ('my_module เริ่มต้น');
จากนั้นใช้รหัสต่อไปนี้เพื่อโหลดโมดูล:
การคัดลอกรหัสมีดังนี้:
var mymoduleinstance1 = ต้องการ ('./ my_module');
มันสร้างผลลัพธ์ต่อไปนี้:
การคัดลอกรหัสมีดังนี้:
โมดูล my_module เริ่มต้น ...
my_module เริ่มต้น
ถ้าเรานำเข้าสองครั้ง:
การคัดลอกรหัสมีดังนี้:
var mymoduleinstance1 = ต้องการ ('./ my_module');
var mymoduleinstance2 = ต้องการ ('./ my_module');
เอาต์พุตยังคง:
การคัดลอกรหัสมีดังนี้:
โมดูล my_module เริ่มต้น ...
my_module เริ่มต้น
กล่าวคือรหัสการเริ่มต้นของโมดูลจะดำเนินการเพียงครั้งเดียว เมื่อคุณสร้างโมดูลของคุณเองหากรหัสการเริ่มต้นของโมดูลมีรหัสที่อาจมีผลข้างเคียงคุณต้องให้ความสนใจเป็นพิเศษกับคุณสมบัตินี้
สรุป
โหนดยกเลิกขอบเขตส่วนกลางเริ่มต้นของ JavaScript และใช้ระบบโมดูล CommonJS แทนเพื่อให้คุณสามารถจัดระเบียบรหัสของคุณได้ดีขึ้นและหลีกเลี่ยงปัญหาด้านความปลอดภัยและข้อบกพร่องมากมาย คุณสามารถใช้ฟังก์ชั่นที่ต้องการเพื่อโหลดโมดูลหลักโมดูลบุคคลที่สามหรือโหลดโมดูลของคุณเองจากไฟล์และไดเรกทอรี
คุณยังสามารถใช้เส้นทางสัมพัทธ์หรือสัมบูรณ์เพื่อโหลดโมดูลที่ไม่ใช่คอร์ หากคุณใส่โมดูลในไดเรกทอรี Node_Modules หรือสำหรับโมดูลที่ติดตั้งด้วย NPM คุณยังสามารถใช้ชื่อโมดูลเพื่อโหลดได้โดยตรง
หมายเหตุของนักแปล:
ขอแนะนำให้ผู้อ่านอ่านบทโมดูลของเอกสารอย่างเป็นทางการ โดยส่วนตัวแล้วฉันรู้สึกว่ามันชัดเจนกว่าผู้เขียน มีการแนบตัวอย่างที่เป็นตัวแทนอย่างมากซึ่งจะช่วยได้อย่างดีในการทำความเข้าใจการโหลดโมดูลโหนด ต่อไปนี้อ้างถึง:
การคัดลอกรหัสมีดังนี้:
ใช้ต้องการ (x) เพื่อโหลดโมดูลภายใต้เส้นทาง y
1. ถ้า x เป็นโมดูลหลัก
. โหลดและส่งคืนโมดูลหลัก
ข. จบ
2. ถ้า X เริ่มต้นด้วย './' หรือ '/' หรือ '../
. load_as_file (y + x)
ข. load_as_directory (y + x)
3. load_node_modules (x, dirname (y))
4. โยนข้อยกเว้น: "ไม่พบ"
load_as_file (x)
1. ถ้า x เป็นไฟล์ให้โหลด x เป็นสคริปต์ JavaScript และสิ้นสุดหลังจากโหลด
2. ถ้า x.js เป็นไฟล์ให้โหลด x.js เป็นสคริปต์ JavaScript และสิ้นสุดหลังจากโหลด
3. ถ้า x.node เป็นไฟล์ให้โหลด x.node เป็นปลั๊กอินไบนารีโหนดและสิ้นสุดหลังจากโหลด
load_as_directory (x)
1. ถ้าไฟล์ x/package.json มีอยู่
. Parses x/package.json และค้นหาฟิลด์ "หลัก"
ข. M = x + (ค่าของฟิลด์หลัก)
ค. load_as_file (m)
2. หากไฟล์ x/index.js มีอยู่ให้โหลด x/index.js เป็นสคริปต์ JavaScript และสิ้นสุดหลังจากโหลด
3. หากมีไฟล์ x/index.node ให้โหลด x/index.node เป็นปลั๊กอินไบนารีโหนดและสิ้นสุดหลังจากโหลด
load_node_modules (x, start)
1. dirs = node_modules_paths (เริ่มต้น)
2. ดำเนินการต่อไปนี้สำหรับแต่ละไดเรกทอรี DIR ภายใต้ DIRS:
. load_as_file (dir/x)
ข. load_as_directory (dir/x)
node_modules_paths (เริ่มต้น)
1. ส่วนต่าง ๆ = Path Split (เริ่มต้น)
2. ยังรูท = ดัชนีของอินสแตนซ์แรกของ "node_modules" ในส่วนหรือ 0
3. ยัง i = จำนวนชิ้นส่วน - 1
4. ยัง dirs = []
5. ในขณะที่ฉัน> รูท
. หากชิ้นส่วน [i] = "node_modules" การดำเนินการติดตามผลจะดำเนินต่อไปมิฉะนั้นลูปถัดไป
ค. dir = path join (ส่วน [0 .. i] + "node_modules"))
ข. dirs = dirs + dir
ค. ฉัน = i - 1
6. กลับไปที่ Dirs