ประกาศฟังก์ชันในส่วนการประกาศ โครงสร้างโปรแกรม นิพจน์และตัวดำเนินการใน JavaScript
สวัสดีทุกคน! ในบทความนี้ฉันต้องการพูดคุยเกี่ยวกับอะไร เช่นการประกาศฟังก์ชันและการแสดงออกของฟังก์ชันในภาษาโปรแกรม จาวาสคริปต์.
ไซต์มีบทความเกี่ยวกับฟังก์ชันคืออะไร วิธีสร้างและใช้งานแล้ว หากยังไม่ได้อ่านก็สามารถอ่านได้
บทความนั้นก็พูดถึง ประกาศฟังก์ชัน.
ถ้าอยากถาม การแสดงออกของฟังก์ชันจากนั้นคุณต้องเขียนดังนี้:
Var func = function(a, b) ( ส่งคืน a + b; );
เหล่านั้น. เรากำหนดฟังก์ชันให้กับตัวแปร โปรดทราบว่ามีเครื่องหมายอัฒภาคต่อท้ายและจะต้องดำเนินการนี้เสมอ เนื่องจาก นี่เป็นเพียงค่าของตัวแปรในหน่วย ประกาศฟังก์ชันไม่จำเป็นต้องใช้อัฒภาค ที่จริงแล้วถ้าคุณไม่ใส่เครื่องหมายอัฒภาค ก็ไม่น่าจะมีอะไรเลวร้ายเกิดขึ้น แต่มีบางสถานการณ์ที่สิ่งนี้สามารถเล่นตลกร้ายกับคุณได้ และจากนั้นการค้นหาข้อผิดพลาดนี้จะค่อนข้างยาก
ตอนนี้เรามาพูดถึงความแตกต่างระหว่างการประกาศฟังก์ชันทั้งสองนี้
การประกาศฟังก์ชั่น
ผลรวม();ผลรวมฟังก์ชัน() (
alert("ได้ผล!");
}
ดังนั้น หากคุณคิด นี่คือคำตอบที่ถูกต้อง: ใช่, จะทำงาน.
สิ่งนี้เป็นไปได้อย่างไร?
คำตอบนั้นง่ายมาก ความจริงก็คือก่อนที่จะรันโค้ดล่ามจะต้องผ่านมันและรวบรวมการประกาศตัวแปรและฟังก์ชันทั้งหมดไว้ในที่พิเศษ ปรากฎว่าเขาซึ่งเป็นล่ามรู้ซอร์สโค้ดทั้งหมดของฟังก์ชันแล้วและสามารถเรียกมันได้แม้ว่าจะเขียนโค้ดต่ำกว่าก็ตาม
การแสดงออกของฟังก์ชัน
ทุกสิ่งที่นี่ตรงกันข้ามทุกประการ
ฟังก์ชั่น Var = ฟังก์ชั่น() (
alert("ได้ผล!");
};
ล่ามจะเรียนรู้เกี่ยวกับฟังก์ชันดังกล่าวในโค้ดเท่านั้น ดังนั้นตัวอย่างข้างต้นจะไม่ทำงาน อย่างไรก็ตาม หากคุณเขียนการเรียกใช้ฟังก์ชันด้านล่าง ทุกอย่างก็จะทำงานได้
ทำไมเราต้องมีการแสดงออกของฟังก์ชัน?
อันที่จริงมีการใช้ในหลาย ๆ ที่ แต่ฉันจะให้ตัวอย่างที่ซ้ำซากอย่างยิ่งที่นี่
ถ้า(อายุ >= 18) (
var func = ฟังก์ชั่น() (
alert("ยินดีต้อนรับ!");
};
) อื่น (
var func = ฟังก์ชั่น() (
alert("ยังเร็วไปสำหรับคุณ!");
};
}
ตอนนี้ขึ้นอยู่กับเงื่อนไขในตัวแปร ฟังก์ชั่นซอร์สโค้ดที่แตกต่างกันจะถูกเขียน ดังนั้น ฟังก์ชันจะทำงานแตกต่างออกไป
กับ ประกาศฟังก์ชันเคล็ดลับดังกล่าวจะไม่ทำงาน
ถ้า(อายุ >= 18) (
ฟังก์ชัน ฟังก์ชัน() (
alert("ยินดีต้อนรับ!");
}
) อื่น (
ฟังก์ชัน ฟังก์ชัน() (
alert("ยังเร็วไปสำหรับคุณ!");
}
}
นี่เป็นอีกปัญหาหนึ่งสำหรับคุณ ลองคิดว่าโค้ดด้านบนนี้จะทำอะไรและทำอะไร เตือน(ฟังก์ชันไหน) จะทำงานในที่สุด
ล่ามจะดูโค้ดจากบนลงล่าง ดังนั้นมันจะเขียนค่าของฟังก์ชันสุดท้ายแล้วเรียกมัน
ดังนั้น ฉันหวังว่าคุณจะเข้าใจความแตกต่างระหว่างการประกาศฟังก์ชัน 2 รายการนี้
ที่ การทำงานคำหลักสามารถใช้เพื่อกำหนดฟังก์ชันภายในนิพจน์
แหล่งที่มาของตัวอย่างเชิงโต้ตอบนี้จัดเก็บไว้ในที่เก็บ GitHub หากคุณต้องการมีส่วนร่วมในโครงการตัวอย่างเชิงโต้ตอบ โปรดโคลน https://github.com/mdn/interactive-examples และส่งคำขอดึงถึงเรา
ไวยากรณ์
var myFunction = ฟังก์ชั่น [ ชื่อ]([พารามิเตอร์1[, พารามิเตอร์2[, ..., พารามิเตอร์N]]]) { งบ };พารามิเตอร์
name ชื่อฟังก์ชัน สามารถละเว้นได้ ซึ่งในกรณีนี้คือฟังก์ชัน ไม่ระบุชื่อ. ชื่อนี้ใช้เฉพาะในเนื้อหาของฟังก์ชันเท่านั้น paramN ชื่อของอาร์กิวเมนต์ที่จะส่งผ่านไปยังฟังก์ชัน งบ ข้อความที่ประกอบด้วยเนื้อความของฟังก์ชันคำอธิบาย
นิพจน์ฟังก์ชันจะคล้ายกันมากและมีไวยากรณ์เกือบจะเหมือนกันกับคำสั่งฟังก์ชัน (ดูรายละเอียดในคำสั่งฟังก์ชัน) ความแตกต่างที่สำคัญระหว่างนิพจน์ฟังก์ชันและคำสั่งฟังก์ชันคือ ชื่อฟังก์ชันซึ่งสามารถละเว้นได้ในนิพจน์ฟังก์ชันเพื่อสร้าง ไม่ระบุชื่อฟังก์ชั่น. นิพจน์ฟังก์ชันสามารถใช้เป็น IIFE (นิพจน์ฟังก์ชันที่เรียกใช้ทันที) ซึ่งจะทำงานทันทีที่มีการกำหนดไว้ ดูบทเกี่ยวกับฟังก์ชันสำหรับข้อมูลเพิ่มเติม
การยกนิพจน์ฟังก์ชัน
นิพจน์ฟังก์ชันใน JavaScript จะไม่ถูกยกขึ้น ซึ่งแตกต่างจากการประกาศฟังก์ชัน คุณไม่สามารถใช้นิพจน์ฟังก์ชันก่อนที่จะกำหนดได้:
Console.log(notHoisted) // undefinition //ถึงแม้ว่าชื่อตัวแปรจะถูกยกขึ้น แต่คำจำกัดความกลับไม่ได้เป็นเช่นนั้น ดังนั้นจึงไม่ได้กำหนดไว้ ไม่ยก(); // TypeError: notHoisted ไม่ใช่ฟังก์ชัน var notHoisted = function() ( console.log("bar"); );
นิพจน์ฟังก์ชันที่มีชื่อ
หากคุณต้องการอ้างถึงฟังก์ชันปัจจุบันภายในเนื้อหาของฟังก์ชัน คุณต้องสร้างนิพจน์ฟังก์ชันที่มีชื่อ ชื่อนี้จะอยู่ในท้องที่เฉพาะกับเนื้อหาของฟังก์ชัน (ขอบเขต) . นอกจากนี้ยังหลีกเลี่ยงการใช้คุณสมบัติ arguments.callee ที่ไม่เป็นไปตามมาตรฐานอีกด้วย
Var math = ( "factit": function factorial(n) ( console.log(n) if (n<= 1) { return 1; } return n * factorial(n - 1); } }; math.factit(3) //3;2;1;
ตัวแปรที่นิพจน์ฟังก์ชันถูกกำหนดให้จะมีคุณสมบัติของชื่อ ชื่อจะไม่เปลี่ยนแปลงหากถูกกำหนดให้กับตัวแปรอื่น หากละเว้นชื่อฟังก์ชัน มันจะเป็นชื่อตัวแปร (ชื่อโดยนัย) หากมีชื่อฟังก์ชัน จะเป็นชื่อฟังก์ชัน (ชื่อที่ชัดเจน) นอกจากนี้ยังใช้กับฟังก์ชันลูกศรด้วย (ลูกศรไม่มีชื่อ ดังนั้นคุณจึงสามารถตั้งชื่อโดยนัยให้กับตัวแปรได้เท่านั้น)
Var foo = function() () foo.name // "foo" var foo2 = foo foo2.name // "foo" var bar = ฟังก์ชั่น baz() () bar.name // "baz" console.log(foo === foo2); // true console.log(typeof baz); // ไม่ได้กำหนด console.log(bar === baz); // false (ข้อผิดพลาดเนื่องจาก baz == ไม่ได้กำหนด)
ตัวอย่าง
ตัวอย่างต่อไปนี้กำหนดฟังก์ชันที่ไม่มีชื่อและกำหนดให้กับ x ฟังก์ชันคืนค่ากำลังสองของอาร์กิวเมนต์:
Var x = function(y) ( ส่งคืน y * y; ); button.addEventListener("click", function(event) ( console.log("button is clicked!") ))
ข้อมูลจำเพาะ
ข้อมูลจำเพาะ | สถานะ | ความคิดเห็น |
---|---|---|
ECMAScript ร่างล่าสุด (ECMA-262) |
ร่าง | |
ECMAScript 2015 (ฉบับที่ 6, ECMA-262) คำจำกัดความของ "คำจำกัดความฟังก์ชัน" ในข้อกำหนดนั้น |
มาตรฐาน | |
ECMAScript 5.1 (ECMA-262) |
มาตรฐาน | |
ECMAScript ฉบับที่ 3 (ECMA-262) คำจำกัดความของ "คำจำกัดความฟังก์ชัน" ในข้อกำหนดนั้น |
มาตรฐาน | คำจำกัดความเริ่มต้น ใช้งานใน JavaScript 1.5 |
ความเข้ากันได้ของเบราว์เซอร์
ตารางความเข้ากันได้ในหน้านี้สร้างขึ้นจากข้อมูลที่มีโครงสร้าง หากคุณต้องการมีส่วนร่วมในข้อมูล โปรดตรวจสอบ https://github.com/mdn/browser-compat-data และส่งคำขอดึงถึงเรา
อัปเดตข้อมูลความเข้ากันได้บน GitHub
เดสก์ทอป | มือถือ | เซิร์ฟเวอร์ | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
โครเมียม | ขอบ | ไฟร์ฟอกซ์ | อินเทอร์เน็ตเอ็กซ์พลอเรอร์ | โอเปร่า | ซาฟารี | มุมมองเว็บ Android | โครมสำหรับแอนดรอยด์ | ไฟร์ฟอกซ์สำหรับ Android | โอเปร่าสำหรับ Android | ซาฟารีบน iOS | ซัมซุงอินเตอร์เน็ต | โหนด js | |
การทำงาน | Chrome รองรับเต็มรูปแบบ ใช่ | ขอบสนับสนุนเต็ม 12 | Firefox รองรับเต็มรูปแบบ 1 | การสนับสนุน IE เต็มรูปแบบ ใช่ | รองรับ Opera เต็มรูปแบบ ใช่ | รองรับ Safari เต็มรูปแบบ ใช่ | รองรับ WebView Android เต็มรูปแบบ ใช่ | รองรับ Chrome Android เต็มรูปแบบใช่ | Firefox Android รองรับเต็มรูปแบบ 4 | รองรับ Opera Android เต็มรูปแบบ ใช่ | Safari iOS รองรับเต็มรูปแบบ ใช่ | Samsung Internet Android รองรับเต็มรูปแบบ ใช่ | nodejs รองรับเต็มที่ ใช่ |
เครื่องหมายจุลภาคต่อท้ายในพารามิเตอร์ | การสนับสนุน Chrome เต็มรูปแบบ 58 | Edge ไม่มีหมายเลขรองรับ | Firefox รองรับเต็มรูปแบบ 52 | IE ไม่มีหมายเลขรองรับ | โอเปร่าสนับสนุนอย่างเต็มที่ 45 | Safari ไม่มีหมายเลขรองรับ | รองรับ WebView Android เต็มรูปแบบ 58 | Chrome Android รองรับเต็มรูปแบบ 58 | Firefox Android รองรับเต็มรูปแบบ 52 | Opera Android รองรับเต็มรูปแบบ 43 | Safari iOS ไม่มีหมายเลขรองรับ | Samsung Internet Android รองรับเวอร์ชันเต็ม 7.0 | nodejs รองรับ 8.0.0 เต็มรูปแบบ |
ตำนาน
การสนับสนุนอย่างเต็มที่การสนับสนุนอย่างเต็มที่ ไม่สนับสนุนไม่สนับสนุนเนื่องจากเป็นวัตถุภาษา C จึงต้องประกาศฟังก์ชัน การประกาศฟังก์ชันผู้ใช้ เช่น การประกาศดำเนินการในสองรูปแบบ - ในรูปแบบของคำอธิบายและในรูปแบบของคำจำกัดความ
คำอธิบายของฟังก์ชันประกอบด้วยการนำเสนอไฟล์โปรแกรมของต้นแบบก่อน ต้นแบบฟังก์ชันแจ้งให้คอมไพลเลอร์ทราบว่าคำจำกัดความแบบเต็ม (ข้อความเต็ม) จะได้รับในภายหลังในข้อความโปรแกรม: ในไฟล์ปัจจุบันหรือไฟล์ต้นฉบับอื่น หรืออยู่ในไลบรารี
มาตรฐานภาษาใช้วิธีการประกาศฟังก์ชันต่อไปนี้:
result_typeบัตรประจำตัวประชาชน _functions(ตัวแปร type1, ..., ตัวแปรประเภท N);
โปรดทราบว่าไม่จำเป็นต้องระบุตัวระบุตัวแปรในวงเล็บต้นแบบ เนื่องจากคอมไพเลอร์ภาษาไม่ได้ประมวลผลตัวแปรเหล่านั้น
คำอธิบายต้นแบบช่วยให้คอมไพลเลอร์ตรวจสอบว่าประเภทและจำนวนพารามิเตอร์ตรงกันเมื่อมีการเรียกใช้ฟังก์ชันจริง
ตัวอย่างคำอธิบายฟังก์ชันสนุกๆ พร้อมรายการพารามิเตอร์:
ลอยสนุก (int, float, int, int);
คำจำกัดความที่สมบูรณ์ของฟังก์ชันมีดังนี้:
result_typeบัตรประจำตัวประชาชน _functions (รายการพารามิเตอร์)
รหัสฟังก์ชัน
ประเภทผลลัพธ์จะกำหนดประเภทของนิพจน์ที่มีค่าจะถูกส่งกลับไปยังจุดการโทรโดยใช้ตัวดำเนินการ กลับ<выражение> .
หากไม่ได้ระบุประเภทฟังก์ชัน ระบบจะใช้ประเภทเริ่มต้นแทน ภายใน .
รายการพารามิเตอร์ประกอบด้วยรายการประเภทพารามิเตอร์และตัวระบุพารามิเตอร์ คั่นด้วยเครื่องหมายจุลภาค
ฟังก์ชันอาจไม่มีพารามิเตอร์ แต่จำเป็นต้องมีวงเล็บไม่ว่าในกรณีใด
หากฟังก์ชันไม่ส่งคืนค่าใด ๆ จะต้องประกาศให้เป็นฟังก์ชันประเภทนั้น เป็นโมฆะ (ว่างเปล่า).
ในกรณีนี้ผู้ปฏิบัติงาน กลับ คุณไม่จำเป็นต้องใส่มัน
ฟังก์ชันสามารถมีได้หลายคำสั่ง กลับ แต่อาจจะไม่มีเลย ในกรณีเช่นนี้ การกลับไปยังโปรแกรมที่เรียกจะเกิดขึ้นหลังจากดำเนินการคำสั่งสุดท้ายในฟังก์ชันแล้ว
ตัวอย่างของฟังก์ชันที่กำหนดค่าที่น้อยที่สุดของตัวแปรจำนวนเต็มสองตัว:
int นาที (int x, int y)
กลับ(x
ต้องใช้ฟังก์ชันทั้งหมดที่ส่งคืนค่าทางด้านขวาของนิพจน์ C มิฉะนั้นผลลัพธ์ที่ส่งคืนจะหายไป
หากฟังก์ชันไม่มีรายการพารามิเตอร์ เมื่อประกาศฟังก์ชันดังกล่าว แนะนำให้ระบุคีย์เวิร์ดที่เป็นโมฆะในวงเล็บด้วย ตัวอย่างเช่น, เป็นโมฆะหลัก (เป็นโมฆะ).
นิพจน์ใน JavaScriptเป็นการรวมกัน ตัวถูกดำเนินการและ ตัวดำเนินการ.
การดำเนินงานในนิพจน์จะถูกดำเนินการตามลำดับตามค่าลำดับความสำคัญ (ยิ่งค่าลำดับความสำคัญสูงเท่าใดก็ยิ่งสูงเท่านั้น) ผลลัพธ์ที่ส่งคืนไม่ได้เป็นประเภทเดียวกันกับประเภทข้อมูลที่กำลังประมวลผลเสมอไป ตัวอย่างเช่น การดำเนินการเปรียบเทียบเกี่ยวข้องกับตัวถูกดำเนินการประเภทต่างๆ แต่ผลลัพธ์ที่ส่งคืนจะเป็นประเภทบูลีนเสมอ
ข้าว. 1. โครงสร้างนิพจน์ใน JavaScriptตัวดำเนินการคือข้อมูลที่ประมวลผลโดยสคริปต์ JavaScript ตัวถูกดำเนินการอาจเป็นชนิดข้อมูลแบบง่ายหรือแบบซับซ้อน เช่นเดียวกับนิพจน์อื่นๆ
ผู้ประกอบการเป็นสัญลักษณ์ภาษาที่ใช้ดำเนินการต่างๆ กับข้อมูล ตัวดำเนินการสามารถเขียนได้โดยใช้อักขระเครื่องหมายวรรคตอนหรือคำสำคัญ
ขึ้นอยู่กับจำนวนตัวถูกดำเนินการ ตัวดำเนินการประเภทต่างๆ ต่อไปนี้จะมีความโดดเด่น:
เอกนารี— ตัวถูกดำเนินการหนึ่งตัวเกี่ยวข้องกับการปฏิบัติการ
ไบนารี่— การดำเนินการเกี่ยวข้องกับตัวถูกดำเนินการสองตัว
ประกอบไปด้วย- รวมตัวถูกดำเนินการสามตัวเข้าด้วยกัน
รูปแบบการแสดงออกที่ง่ายที่สุดคือ ตัวอักษร— สิ่งที่ประเมินตัวเอง เช่น หมายเลข 100 สตริง "Hello world" ตัวแปรยังสามารถเป็นนิพจน์ได้ เนื่องจากตัวแปรจะประเมินค่าที่กำหนดให้กับตัวแปรนั้น
นิพจน์และตัวดำเนินการใน JavaScript
1. ตัวดำเนินการทางคณิตศาสตร์
ตัวดำเนินการทางคณิตศาสตร์ออกแบบมาเพื่อดำเนินการทางคณิตศาสตร์ โดยทำงานกับตัวถูกดำเนินการตัวเลข (หรือตัวแปรที่เก็บค่าตัวเลข) โดยส่งคืนค่าตัวเลขตามผลลัพธ์
หากหนึ่งในตัวถูกดำเนินการเป็นสตริง ตัวแปล JavaScript จะพยายามแปลงเป็นประเภทตัวเลข จากนั้นดำเนินการตามความเหมาะสม หากไม่สามารถแปลงประเภทได้ ผลลัพธ์จะเป็น NaN (ไม่ใช่ตัวเลข)
ผู้ปฏิบัติงาน/ปฏิบัติการ | คำอธิบาย | ลำดับความสำคัญ |
---|---|---|
+ นอกจากนี้ | เพิ่มตัวถูกดำเนินการที่เป็นตัวเลข หากหนึ่งในตัวถูกดำเนินการเป็นสตริง ผลลัพธ์ของนิพจน์จะเป็นสตริง | 12 |
- การลบ | ลบตัวถูกดำเนินการที่สองจากตัวแรก | 12 |
- ยูนินารีลบ | แปลงจำนวนบวกให้เป็นจำนวนลบและในทางกลับกัน | 14 |
* การคูณ | คูณตัวถูกดำเนินการสองตัว | 13 |
/ แผนก | แบ่งตัวถูกดำเนินการตัวแรกด้วยตัวที่สอง ผลลัพธ์ของการหารอาจเป็นจำนวนเต็มหรือเลขทศนิยมก็ได้ | 13 |
% การแบ่งโมดูโล่ (ส่วนที่เหลือ) | คำนวณส่วนที่เหลือซึ่งเป็นผลมาจากการหารจำนวนเต็มของตัวถูกดำเนินการตัวแรกด้วยตัวที่สอง ใช้กับทั้งจำนวนเต็มและจำนวนจุดลอยตัว | 13 |
2. ผู้ดำเนินการมอบหมาย
ผู้ดำเนินการที่ได้รับมอบหมายใช้ในการกำหนดค่าให้กับตัวแปร ตัวดำเนินการแบบรวมช่วยให้คุณสามารถจัดเก็บค่าดั้งเดิมและค่าที่ตามมาในตัวแปรเดียว
วาร์ ก = 5; // กำหนดค่าตัวเลข 5 ให้กับตัวแปร a var b = "hello"; // เก็บสตริงเฮลโลว์ไว้ในตัวแปร b var m = n = z = 10; // กำหนดตัวแปร m, n, z ค่าตัวเลข 10 x += 10; // เทียบเท่ากับ x = x + 10; x -= 10; // เทียบเท่ากับ x = x - 10; x *= 10; // เทียบเท่ากับ x = x * 10; x /= 10; // เทียบเท่ากับ x = x / 10; x %= 10; // เทียบเท่ากับ x = x % 10;3. ตัวดำเนินการเพิ่มและลด
การดำเนินงาน การเพิ่มขึ้นและการลดลงเป็นเอกพจน์และเพิ่มและลดค่าของตัวถูกดำเนินการทีละหนึ่ง ตัวถูกดำเนินการอาจเป็นตัวแปร องค์ประกอบอาร์เรย์ หรือคุณสมบัติของวัตถุ ส่วนใหญ่แล้ว การดำเนินการดังกล่าวจะใช้เพื่อเพิ่มตัวนับในลูป
var x = y = m = n = 5, z, s, k, l; z = ++x * 2; /* จากการคำนวณจะส่งกลับค่า z = 12, x = 6 เช่น ค่าของ x จะเพิ่มขึ้น 1 ก่อนจากนั้นจึงดำเนินการคูณ */ s = y++ * 2; /* จากการคำนวณจะส่งกลับค่า s = 10, y = 6 เช่น ขั้นแรก ดำเนินการคูณ จากนั้นค่าที่เพิ่มขึ้น 1 จะถูกเก็บไว้ในตัวแปร y */ k = --m * 2; // ส่งกลับค่า k = 8, m = 4 l = n-- * 2; // ส่งกลับค่า l = 10, n = 44. ตัวดำเนินการเปรียบเทียบ
ตัวดำเนินการเปรียบเทียบใช้เพื่อจับคู่ตัวถูกดำเนินการ ผลลัพธ์ของนิพจน์สามารถเป็นหนึ่งในสองค่า - จริงหรือเท็จ ตัวถูกดำเนินการไม่เพียงแต่เป็นตัวเลขเท่านั้น แต่ยังรวมถึงสตริง ค่าตรรกะ และอ็อบเจ็กต์อีกด้วย อย่างไรก็ตาม การเปรียบเทียบสามารถทำได้กับตัวเลขและสตริงเท่านั้น ดังนั้นตัวถูกดำเนินการที่ไม่ใช่ตัวเลขหรือสตริงจึงจะถูกแปลง
หากไม่สามารถแปลงตัวถูกดำเนินการทั้งสองเป็นตัวเลขหรือสตริงได้สำเร็จ ตัวดำเนินการจะส่งคืนค่า false เสมอ
หากตัวถูกดำเนินการทั้งสองตัวเป็นสตริง/ตัวเลข หรือสามารถแปลงเป็นสตริง/ตัวเลขได้ ระบบจะเปรียบเทียบค่าเหล่านั้นเป็นสตริง/ตัวเลข
ถ้าตัวถูกดำเนินการตัวหนึ่งเป็นสตริง/แปลงเป็นสตริง และอีกตัวเป็นตัวเลข/แปลงเป็นตัวเลข ตัวดำเนินการจะพยายามแปลงสตริงเป็นตัวเลขและทำการเปรียบเทียบตัวเลข หากสตริงไม่ใช่ตัวเลข สตริงนั้นจะถูกแปลงเป็น NaN และผลลัพธ์ของการเปรียบเทียบจะเป็น false
ส่วนใหญ่แล้วการดำเนินการเปรียบเทียบจะใช้เมื่อจัดสาขาในโปรแกรม
ผู้ปฏิบัติงาน/ปฏิบัติการ | คำอธิบาย | ลำดับความสำคัญ |
---|---|---|
== ความเท่าเทียมกัน | ทดสอบสองค่าด้วยค่าเดียวกัน อนุญาตให้แปลงประเภทได้ คืนค่าเป็นจริงหากตัวถูกดำเนินการเหมือนกัน และคืนค่าเป็นเท็จหากต่างกัน | 9 |
!= อสมการ | คืนค่าเป็นจริงหากตัวถูกดำเนินการไม่เท่ากัน | 9 |
=== ตัวตน | ทดสอบตัวถูกดำเนินการสองตัวสำหรับ "ข้อมูลประจำตัว" โดยใช้คำจำกัดความที่เข้มงวดของการจับคู่ คืนค่าเป็นจริงหากตัวถูกดำเนินการเท่ากันโดยไม่มีการแปลงประเภท | 9 |
!== ไม่มีตัวตน | ดำเนินการยืนยันตัวตน คืนค่าเป็นจริงหากตัวถูกดำเนินการไม่เท่ากันโดยไม่มีการแปลงประเภท | 9 |
> เพิ่มเติม | คืนค่าเป็นจริงหากตัวถูกดำเนินการตัวแรกมากกว่าตัวที่สอง มิฉะนั้นจะส่งคืนค่าเท็จ | 10 |
>= มากกว่าหรือเท่ากับ | คืนค่าเป็นจริงหากตัวถูกดำเนินการตัวแรกไม่น้อยกว่าตัวที่สอง มิฉะนั้นจะส่งคืนค่าเท็จ | 10 |
คืนค่าเป็นจริงหากตัวถูกดำเนินการตัวแรกน้อยกว่าตัวที่สอง มิฉะนั้นจะส่งกลับค่าเท็จ | 10 | |
คืนค่าเป็นจริงหากตัวถูกดำเนินการตัวแรกไม่มากกว่าตัวที่สอง มิฉะนั้นจะส่งคืนค่าเท็จ | 10 |
5. ตัวดำเนินการเชิงตรรกะ
ตัวดำเนินการเชิงตรรกะอนุญาตให้คุณรวมเงื่อนไขที่ส่งคืนค่าบูลีน มักใช้ในคำสั่ง if Conditional
(2 < 3) && (3===3); // вернет true, так как выражения в обеих скобках дают true (x < 10 && x >0); // จะคืนค่าเป็นจริงหาก x อยู่ในช่วงตั้งแต่ 0 ถึง 10 !false; // คืนค่าจริง6. ตัวดำเนินการ Bitwise
ตัวดำเนินการ Bitwiseดำเนินการกับตัวถูกดำเนินการเป็นลำดับ 32 บิตของค่าและศูนย์ และส่งกลับค่าตัวเลขที่ระบุผลลัพธ์ของการดำเนินการ โดยเขียนในรูปแบบทศนิยม ตัวเลขจำนวนเต็มถือเป็นตัวถูกดำเนินการ ส่วนเศษส่วนของตัวถูกดำเนินการจะถูกละทิ้ง การดำเนินการระดับบิตสามารถใช้ได้ เช่น เมื่อเข้ารหัสข้อมูล ทำงานกับแฟล็ก และกำหนดสิทธิ์การเข้าถึง
ผู้ปฏิบัติงาน/ปฏิบัติการ | คำอธิบาย | ลำดับความสำคัญ |
---|---|---|
& ระดับบิต และ | ถ้าทั้งสองบิตเป็น 1 บิตผลลัพธ์จะเป็น 1 มิฉะนั้นผลลัพธ์จะเป็น 0 | 8 |
| บิตไวส์หรือ | หากตัวถูกดำเนินการตัวใดตัวหนึ่งมี 1 ที่ตำแหน่ง ผลลัพธ์ก็จะมี 1 อยู่ที่ตำแหน่งนั้นด้วย มิฉะนั้น ผลลัพธ์ที่ตำแหน่งนั้นจะเป็น 0 | 6 |
↑ เอกสิทธิ์เฉพาะบุคคล หรือ | หากค่าเดียวเท่านั้นที่มี 1 ที่ตำแหน่งใดๆ ผลลัพธ์ก็จะมี 1 ที่ตำแหน่งนั้น มิฉะนั้น ผลลัพธ์ที่ตำแหน่งนั้นจะเป็น 0 | 7 |
~ การปฏิเสธ | การดำเนินการปฏิเสธระดับบิตจะดำเนินการกับการแทนค่าไบนารีของนิพจน์ ตำแหน่งใดๆ ที่มี 1 ในนิพจน์เดิมจะถูกแทนที่ด้วย 0 ตำแหน่งใดๆ ที่มี 0 ในนิพจน์ดั้งเดิมจะกลายเป็น 0 จำนวนบวกเริ่มต้นที่ 0 จำนวนลบเริ่มต้นที่ -1 ดังนั้น ~ n == -(n+1) | 14 |
ตัวดำเนินการเลื่อนบิตของตัวถูกดำเนินการตัวแรกไปทางซ้ายตามจำนวนตำแหน่งบิตที่กำหนดโดยตัวถูกดำเนินการตัวที่สอง เลขศูนย์ใช้เพื่อเติมตำแหน่งทางด้านขวา ส่งกลับผลลัพธ์ประเภทเดียวกันกับตัวถูกดำเนินการทางซ้าย | 11 | |
>> เลื่อนไปทางขวา | ตัวดำเนินการเลื่อนบิตของตัวถูกดำเนินการตัวแรกไปทางขวาตามจำนวนตำแหน่งบิตที่กำหนดโดยตัวถูกดำเนินการตัวที่สอง ตัวเลขที่ถูกเลื่อนออกนอกช่วงจะถูกลบออก บิตที่สำคัญที่สุด (ที่ 32) จะไม่มีการเปลี่ยนแปลงเพื่อรักษาเครื่องหมายของผลลัพธ์ หากตัวถูกดำเนินการตัวแรกเป็นค่าบวก บิตที่สำคัญที่สุดของผลลัพธ์จะถูกเติมด้วยศูนย์ หากตัวถูกดำเนินการตัวแรกเป็นค่าลบ บิตที่สำคัญที่สุดของผลลัพธ์จะถูกเติมด้วยตัวถูกดำเนินการ การเลื่อนค่าไปทางขวาหนึ่งตำแหน่งจะเทียบเท่ากับการหารด้วย 2 (ทิ้งเศษที่เหลือ) และการเลื่อนไปทางขวาด้วยสองตำแหน่งจะเทียบเท่ากับการหารด้วย 4 เป็นต้น | 11 |
>>> เลื่อนไปทางขวาแบบ Bitwise โดยไม่มีเครื่องหมาย | ตัวดำเนินการเลื่อนบิตของตัวถูกดำเนินการตัวแรกไปทางขวาตามจำนวนตำแหน่งบิตที่กำหนดโดยตัวถูกดำเนินการตัวที่สอง เลขศูนย์จะถูกเพิ่มทางด้านซ้าย โดยไม่คำนึงถึงเครื่องหมายของตัวถูกดำเนินการตัวแรก ตัวเลขที่ถูกเลื่อนออกนอกช่วงจะถูกลบออก | 11 |
7. ตัวดำเนินการสตริง
มีโอเปอเรเตอร์หลายตัวที่ทำงานกับสตริงในลักษณะพิเศษ
"1" + "10"; // กลับ "110" "1" + 10; // ส่งกลับ "110" 2 + 5 + "ดินสอสี"; // ส่งคืน "ดินสอสี 7 แท่ง" "ดินสอสี" + 2 + 5; // ส่งคืน "ดินสอสี 25 แท่ง" "1" > "10"; // กลับเท็จ "10"<= 10; // вернет true "СССР" == "ссср"; // вернет false x = "micro"; x+= "soft"; // вернет "microsoft"8. ผู้ปฏิบัติงานพิเศษ
ผู้ปฏิบัติงาน/ปฏิบัติการ | คำอธิบาย | ลำดับความสำคัญ |
---|---|---|
. การเข้าถึงทรัพย์สิน | เข้าถึงคุณสมบัติของวัตถุ | 15 |
,การคำนวณหลายรายการ | ประเมินนิพจน์อิสระหลายรายการที่เขียนในบรรทัดเดียว | 1 |
การจัดทำดัชนีอาร์เรย์ | เข้าถึงองค์ประกอบอาร์เรย์หรือคุณสมบัติของวัตถุ | 15 |
() การเรียกใช้ฟังก์ชัน, การจัดกลุ่ม | การดำเนินการกลุ่มหรือการเรียกใช้ฟังก์ชัน | 15 |
ประเภทของคำจำกัดความของชนิดข้อมูล | ตัวดำเนินการ Unary ส่งคืนชนิดข้อมูลของตัวถูกดำเนินการ | 14 |
instanceof การตรวจสอบประเภทของวัตถุ | ตัวดำเนินการตรวจสอบว่าวัตถุนั้นเป็นอินสแตนซ์ของคลาสใดคลาสหนึ่งหรือไม่ ตัวถูกดำเนินการทางซ้ายต้องเป็นวัตถุ ตัวถูกดำเนินการทางขวาต้องมีชื่อของคลาสอ็อบเจ็กต์ ผลลัพธ์จะเป็นจริงหากวัตถุทางด้านซ้ายเป็นตัวอย่างของคลาสทางด้านขวา มิฉะนั้นจะเป็นเท็จ | 10 |
ในการตรวจสอบการมีอยู่ของทรัพย์สิน | ตัวถูกดำเนินการทางซ้ายจะต้องเป็นสตริง และตัวถูกดำเนินการทางขวาจะต้องเป็นอาร์เรย์หรือวัตถุ หากค่าทางซ้ายเป็นคุณสมบัติของวัตถุ ผลลัพธ์จะเป็น true | 10 |
ใหม่ การสร้างวัตถุ | ตัวดำเนินการสร้างอ็อบเจ็กต์ใหม่ที่มีคุณสมบัติที่ไม่ได้กำหนดไว้ จากนั้นเรียกใช้ฟังก์ชัน Constructor เพื่อเตรียมใช้งาน (ส่งพารามิเตอร์) สามารถใช้สร้างอาร์เรย์ได้ | 1 |
ลบ ลบ | ตัวดำเนินการอนุญาตให้คุณลบคุณสมบัติออกจากวัตถุหรือองค์ประกอบออกจากอาร์เรย์ คืนค่าเป็นจริงหากการลบสำเร็จ มิฉะนั้นจะคืนค่าเป็นเท็จ เมื่อลบองค์ประกอบอาร์เรย์ ความยาวจะไม่เปลี่ยนแปลง | 14 |
โมฆะ การกำหนดนิพจน์โดยไม่มีค่าส่งคืน | ตัวดำเนินการ Unary ละทิ้งค่าของตัวถูกดำเนินการและส่งกลับค่าที่ขีดล่าง | 14 |
?: ตัวดำเนินการนิพจน์แบบมีเงื่อนไข | ตัวดำเนินการแบบไตรภาคช่วยให้คุณสามารถจัดระเบียบการแยกย่อยแบบง่ายๆ นิพจน์เกี่ยวข้องกับตัวถูกดำเนินการสามตัว ตัวถูกดำเนินการตัวแรกต้องเป็นค่าบูลีนหรือแปลงเป็นหนึ่งตัว และตัวที่สองและสามต้องเป็นค่าใดก็ได้ หากตัวถูกดำเนินการตัวแรกเป็นจริง นิพจน์เงื่อนไขก็จะรับค่าของตัวถูกดำเนินการตัวที่สอง ถ้าเป็นเท็จ - แสดงว่าอันที่สาม | 3 |
9. ความคิดเห็นใน JavaScript
ความคิดเห็นบรรทัดเดียว: คุณต้องนำสัญลักษณ์ด้านหน้าข้อความความคิดเห็น //
ฟังก์ชั่นเป็นหนึ่งในองค์ประกอบพื้นฐานใน JavaScript ฟังก์ชั่นคือขั้นตอน JavaScript ซึ่งเป็นชุดคำสั่งที่ทำงานหรือคำนวณค่า หากต้องการใช้ฟังก์ชัน คุณต้องกำหนดฟังก์ชันไว้ที่ไหนสักแห่งในขอบเขตที่คุณต้องการเรียกใช้ฟังก์ชัน
ก วิธีเป็นฟังก์ชันที่เป็นคุณสมบัติของวัตถุ อ่านเพิ่มเติมเกี่ยวกับออบเจ็กต์และวิธีการในการทำงานกับออบเจ็กต์
ฟังก์ชั่นการโทร
การกำหนดฟังก์ชันไม่ได้ดำเนินการ การกำหนดฟังก์ชันเพียงตั้งชื่อฟังก์ชันและระบุสิ่งที่ต้องทำเมื่อมีการเรียกใช้ฟังก์ชัน กำลังโทรฟังก์ชันจะดำเนินการตามที่ระบุจริง ๆ ด้วยพารามิเตอร์ที่ระบุ ตัวอย่างเช่น หากคุณกำหนดฟังก์ชัน square คุณสามารถเรียกมันได้ดังนี้:
สี่เหลี่ยม(5);
คำสั่งก่อนหน้าเรียกฟังก์ชันด้วยอาร์กิวเมนต์ 5 ฟังก์ชันดำเนินการคำสั่งและส่งกลับค่า 25
ฟังก์ชั่นจะต้องอยู่ในขอบเขตเมื่อมีการเรียกใช้ แต่การประกาศฟังก์ชั่นสามารถยกขึ้นได้ (ปรากฏด้านล่างการโทรในโค้ด) ดังในตัวอย่างนี้:
Console.log (สี่เหลี่ยม (5)); /* ... */ ฟังก์ชั่น สแควร์(n) ( return n * n; )
ขอบเขตของฟังก์ชันคือฟังก์ชันที่ถูกประกาศ หรือทั้งโปรแกรมหากมีการประกาศที่ระดับบนสุด
บันทึก:ใช้งานได้เฉพาะเมื่อกำหนดฟังก์ชันโดยใช้ไวยากรณ์ด้านบน (เช่น ฟังก์ชัน funcName()()) รหัสด้านล่างจะไม่ทำงาน นั่นหมายความว่าการยกฟังก์ชันใช้งานได้เฉพาะกับการประกาศฟังก์ชันเท่านั้น ไม่ใช่กับการแสดงออกของฟังก์ชัน
Console.log (สี่เหลี่ยมจัตุรัส); // ยกกำลังสองด้วยค่าเริ่มต้นที่ไม่ได้กำหนด console.log(สี่เหลี่ยม(5)); // Uncaught TypeError: สแควร์ไม่ใช่ฟังก์ชัน var square = function(n) ( return n * n; )
อาร์กิวเมนต์ของฟังก์ชันไม่ได้จำกัดอยู่เพียงสตริงและตัวเลข คุณสามารถส่งวัตถุทั้งหมดไปยังฟังก์ชันได้ ฟังก์ชัน show_props() (กำหนดใน ) เป็นตัวอย่างของฟังก์ชันที่รับวัตถุเป็นอาร์กิวเมนต์
ฟังก์ชั่นสามารถเรียกตัวเองได้ ตัวอย่างเช่น นี่คือฟังก์ชันที่คำนวณแฟคทอเรียลแบบวนซ้ำ:
ฟังก์ชัน factorial(n) ( if ((n === 0) || (n === 1)) return 1; else return (n * factorial(n - 1)); )
จากนั้นคุณสามารถคำนวณแฟกทอเรียลของหนึ่งถึงห้าได้ดังนี้:
วาร์ ก, ข, ค, ง, อี; ก = แฟกทอเรียล (1); // a รับค่า 1 b = แฟกทอเรียล (2); // b รับค่า 2 c = แฟกทอเรียล (3); // c รับค่า 6 d = แฟกทอเรียล (4); // d รับค่า 24 e = factorial(5); //e รับค่า 120
มีวิธีอื่นในการเรียกใช้ฟังก์ชัน มักมีกรณีที่จำเป็นต้องเรียกใช้ฟังก์ชันแบบไดนามิก หรือจำนวนอาร์กิวเมนต์ของฟังก์ชันแตกต่างกันไป หรือจำเป็นต้องตั้งค่าบริบทของการเรียกใช้ฟังก์ชันเป็นอ็อบเจ็กต์เฉพาะที่กำหนด ณ รันไทม์ ปรากฎว่าฟังก์ชันในตัวมันเองเป็นวัตถุ และวัตถุเหล่านี้ก็มีเมธอดตามลำดับ (ดูวัตถุฟังก์ชัน) หนึ่งในนั้นคือเมธอด Apply() สามารถใช้เพื่อบรรลุเป้าหมายนี้ได้
ขอบเขตของฟังก์ชัน
ตัวแปรที่กำหนดภายในฟังก์ชันไม่สามารถเข้าถึงได้จากทุกที่ภายนอกฟังก์ชัน เนื่องจากตัวแปรถูกกำหนดไว้เฉพาะในขอบเขตของฟังก์ชันเท่านั้น อย่างไรก็ตาม ฟังก์ชันสามารถเข้าถึงตัวแปรและฟังก์ชันทั้งหมดที่กำหนดไว้ภายในขอบเขตที่ถูกกำหนดไว้ กล่าวอีกนัยหนึ่ง ฟังก์ชันที่กำหนดในขอบเขตส่วนกลางสามารถเข้าถึงตัวแปรทั้งหมดที่กำหนดไว้ในขอบเขตส่วนกลางได้ ฟังก์ชันที่กำหนดไว้ภายในฟังก์ชันอื่นยังสามารถเข้าถึงตัวแปรทั้งหมดที่กำหนดไว้ในฟังก์ชันพาเรนต์และตัวแปรอื่นๆ ที่ฟังก์ชันพาเรนต์สามารถเข้าถึงได้
// ตัวแปรต่อไปนี้ถูกกำหนดไว้ในขอบเขตสากล var num1 = 20, num2 = 3, name = "Chamahk"; // ฟังก์ชันนี้ถูกกำหนดไว้ในฟังก์ชันขอบเขตสากล multiply() ( return num1 * num2; ) multiply(); // ส่งคืน 60 // ตัวอย่างฟังก์ชันที่ซ้อนกัน function getScore() ( var num1 = 2, num2 = 3; function add() ( return name + " Score " + (num1 + num2); ) return add(); ) getScore (); // ส่งกลับ "ชะมะคะแนน 5"
ขอบเขตและสแต็กฟังก์ชัน
การเรียกซ้ำ
ฟังก์ชั่นสามารถอ้างถึงและเรียกตัวเองได้ มีสามวิธีสำหรับฟังก์ชันในการอ้างถึงตัวเอง:
- ชื่อของฟังก์ชัน
- ตัวแปรในขอบเขตที่อ้างถึงฟังก์ชัน
ตัวอย่างเช่น พิจารณาคำจำกัดความของฟังก์ชันต่อไปนี้:
Var foo = function bar() ( // คำสั่งไปที่นี่ );
ภายในเนื้อหาของฟังก์ชัน สิ่งต่อไปนี้จะเทียบเท่ากันทั้งหมด:
- บาร์()
- อาร์กิวเมนต์.callee()
- ฟู()
ฟังก์ชันที่เรียกตัวเองว่า a ฟังก์ชันแบบเรียกซ้ำ. ในบางวิธี การเรียกซ้ำจะคล้ายคลึงกับการวนซ้ำ ทั้งสองรันโค้ดเดียวกันหลายครั้ง และทั้งสองจำเป็นต้องมีเงื่อนไข (เพื่อหลีกเลี่ยงการวนซ้ำไม่สิ้นสุด หรือค่อนข้างเป็นการเรียกซ้ำไม่สิ้นสุดในกรณีนี้) ตัวอย่างเช่น วงต่อไปนี้:
วาร์ x = 0; ในขณะที่(x< 10) { // "x < 10" is the loop condition // do stuff x++; }
สามารถแปลงเป็นฟังก์ชันแบบเรียกซ้ำและการเรียกใช้ฟังก์ชันนั้นได้:
Function loop(x) ( if (x >= 10) // "x >= 10" เป็นเงื่อนไขการออก (เทียบเท่ากับ "!(x< 10)") return; // do stuff loop(x + 1); // the recursive call } loop(0);
อย่างไรก็ตาม อัลกอริธึมบางตัวไม่สามารถเป็นการวนซ้ำอย่างง่ายได้ ตัวอย่างเช่น การรับโหนดทั้งหมดของโครงสร้างแบบต้นไม้ (เช่น DOM) ทำได้ง่ายกว่าโดยใช้การเรียกซ้ำ:
ฟังก์ชั่น walkTree(node) ( if (node == null) // return; // ทำบางสิ่งกับ node for (var i = 0; i< node.childNodes.length; i++) { walkTree(node.childNodes[i]); } }
เมื่อเปรียบเทียบกับฟังก์ชันลูป การเรียกซ้ำแต่ละครั้งจะทำการเรียกซ้ำหลายครั้งที่นี่
มีความเป็นไปได้ที่จะแปลงอัลกอริธึมแบบเรียกซ้ำให้เป็นแบบไม่เรียกซ้ำ แต่บ่อยครั้งที่ตรรกะนั้นซับซ้อนกว่ามากและการทำเช่นนี้จำเป็นต้องใช้สแต็ก ในความเป็นจริง การเรียกซ้ำนั้นใช้สแต็ก: สแต็กฟังก์ชัน
พฤติกรรมที่เหมือนสแต็กสามารถเห็นได้ในตัวอย่างต่อไปนี้:
ฟังก์ชั่น foo(i) ( ถ้า (i< 0) return; console.log("begin: " + i); foo(i - 1); console.log("end: " + i); } foo(3); // Output: // begin: 3 // begin: 2 // begin: 1 // begin: 0 // end: 0 // end: 1 // end: 2 // end: 3
ฟังก์ชั่นและการปิดที่ซ้อนกัน
คุณสามารถซ้อนฟังก์ชันภายในฟังก์ชันได้ ฟังก์ชันที่ซ้อนกัน (ภายใน) เป็นส่วนตัวสำหรับฟังก์ชันที่มี (ภายนอก) นอกจากนี้ยังก่อให้เกิด ปิด. การปิดคือนิพจน์ (โดยทั่วไปคือฟังก์ชัน) ที่สามารถมีตัวแปรอิสระร่วมกับสภาพแวดล้อมที่ผูกตัวแปรเหล่านั้น (ซึ่ง "ปิด" นิพจน์)
เนื่องจากฟังก์ชันที่ซ้อนกันเป็นการปิด ซึ่งหมายความว่าฟังก์ชันที่ซ้อนกันสามารถ "สืบทอด" อาร์กิวเมนต์และตัวแปรของฟังก์ชันที่มีอยู่ได้ กล่าวอีกนัยหนึ่ง ฟังก์ชันภายในประกอบด้วยขอบเขตของฟังก์ชันภายนอก
- ฟังก์ชันภายในสามารถเข้าถึงได้จากคำสั่งในฟังก์ชันภายนอกเท่านั้น
- ฟังก์ชันภายในสร้างการปิด: ฟังก์ชันภายในสามารถใช้อาร์กิวเมนต์และตัวแปรของฟังก์ชันภายนอกได้ ในขณะที่ฟังก์ชันภายนอกไม่สามารถใช้อาร์กิวเมนต์และตัวแปรของฟังก์ชันภายในได้
ตัวอย่างต่อไปนี้แสดงฟังก์ชันที่ซ้อนกัน:
ฟังก์ชัน addSquares(a, b) ( function square(x) ( return x * x; ) return square(a) + square(b); ) a = addSquares(2, 3); // ส่งคืน 13 b = addSquares(3, 4); // ส่งคืน 25 c = addSquares(4, 5); // คืนค่า 41
เนื่องจากฟังก์ชันภายในสร้างการปิด คุณจึงสามารถเรียกใช้ฟังก์ชันภายนอกและระบุอาร์กิวเมนต์สำหรับทั้งฟังก์ชันภายนอกและภายในได้:
ฟังก์ชั่นภายนอก(x) ( ฟังก์ชั่นภายใน(y) ( กลับ x + y; ) กลับภายใน; ) fn_inside = ภายนอก(3); // ลองคิดดู: ขอฟังก์ชันที่บวก 3 ให้กับสิ่งที่คุณให้ // it result = fn_inside(5); // ส่งกลับ 8 result1 = ภายนอก (3) (5); // คืนค่า 8
การอนุรักษ์ตัวแปร
สังเกตว่า x จะถูกเก็บรักษาไว้อย่างไรเมื่อส่งคืนภายใน การปิดจะต้องรักษาอาร์กิวเมนต์และตัวแปรไว้ในขอบเขตทั้งหมดที่อ้างอิง เนื่องจากการเรียกแต่ละครั้งอาจมีข้อโต้แย้งที่แตกต่างกัน การปิดใหม่จึงถูกสร้างขึ้นสำหรับการเรียกภายนอกแต่ละครั้ง หน่วยความจำสามารถถูกปลดปล่อยได้เฉพาะเมื่อไม่สามารถเข้าถึงภายในที่ส่งคืนได้อีกต่อไป
สิ่งนี้ไม่แตกต่างจากการจัดเก็บการอ้างอิงในออบเจ็กต์อื่น แต่มักจะชัดเจนน้อยกว่าเนื่องจากไม่ได้ตั้งค่าการอ้างอิงโดยตรงและไม่สามารถตรวจสอบได้
ฟังก์ชันที่ซ้อนกันแบบทวีคูณ
ฟังก์ชันสามารถคูณซ้อนกันได้ เช่น ฟังก์ชัน (A) ที่มีฟังก์ชัน (B) ที่มีฟังก์ชัน (C) การปิดแบบฟอร์มทั้งฟังก์ชัน B และ C ที่นี่ ดังนั้น B จึงสามารถเข้าถึง A และ C สามารถเข้าถึง B ได้ นอกจากนี้ เนื่องจาก C สามารถเข้าถึง B ซึ่งสามารถเข้าถึง A ได้ C จึงสามารถเข้าถึง A ได้ ดังนั้น การปิดจึงสามารถมีหลายขอบเขตได้ พวกมันมีขอบเขตของฟังก์ชันที่มีอยู่ซ้ำ ๆ สิ่งนี้เรียกว่า การผูกมัดขอบเขต. (เหตุใดจึงเรียกว่า "การผูกมัด" จะอธิบายในภายหลัง)
ลองพิจารณาตัวอย่างต่อไปนี้:
ฟังก์ชัน A(x) ( ฟังก์ชั่น B(y) ( ฟังก์ชั่น C(z) ( console.log(x + y + z); ) C(3); ) B(2); ) A(1); // บันทึก 6 (1 + 2 + 3)
ในตัวอย่างนี้ C เข้าถึง B "sy และ A "s x สิ่งนี้สามารถทำได้เนื่องจาก:
- B ก่อให้เกิดการปิดซึ่งรวมถึง A เช่น B สามารถเข้าถึงอาร์กิวเมนต์และตัวแปรของ A
- C ก่อให้เกิดการปิดรวมถึง B.
- เนื่องจากการปิดของ B รวมถึง A การปิดของ C รวมถึง A, C สามารถเข้าถึงทั้ง B และอาร์กิวเมนต์และตัวแปรของ A "กล่าวอีกนัยหนึ่ง C ห่วงโซ่ขอบเขตของ B และ A ตามลำดับนั้น
อย่างไรก็ตามสิ่งที่ตรงกันข้ามไม่เป็นความจริง A ไม่สามารถเข้าถึง C ได้ เนื่องจาก A ไม่สามารถเข้าถึงอาร์กิวเมนต์หรือตัวแปรใดๆ ของ B ซึ่ง C เป็นตัวแปรของ ดังนั้น C ยังคงเป็นส่วนตัวของ B เท่านั้น
ข้อขัดแย้งของชื่อ
เมื่ออาร์กิวเมนต์หรือตัวแปรสองตัวในขอบเขตของการปิดมีชื่อเดียวกัน นั่นก็คือ ความขัดแย้งของชื่อ. ขอบเขตภายในจะมีลำดับความสำคัญมากกว่า ดังนั้นขอบเขตด้านในสุดจะมีความสำคัญสูงสุด ในขณะที่ขอบเขตด้านนอกสุดจะมีความสำคัญน้อยที่สุด นี่คือห่วงโซ่ขอบเขต อันแรกบนห่วงโซ่คือขอบเขตด้านในสุด และอันสุดท้ายคือขอบเขตด้านนอกสุด พิจารณาสิ่งต่อไปนี้:
ฟังก์ชั่นภายนอก() ( var x = 5; ฟังก์ชั่นภายใน(x) ( return x * 2; ) กลับภายใน; ) ภายนอก())(10); // คืนค่า 20 แทนที่จะเป็น 10
ข้อขัดแย้งของชื่อเกิดขึ้นที่คำสั่ง return x และอยู่ระหว่างพารามิเตอร์ x ภายในและตัวแปร s ภายนอก x ห่วงโซ่ขอบเขตที่นี่คือ ( inside , Outside , global object) ดังนั้นภายใน "s x มาก่อนภายนอก "s x และส่งคืน 20 (ภายใน "s x) แทนที่จะเป็น 10 (นอก "s x)
การปิด
การปิดเป็นหนึ่งในคุณสมบัติที่ทรงพลังที่สุดของ JavaScript JavaScript อนุญาตให้มีการซ้อนฟังก์ชันและให้ฟังก์ชันภายในเข้าถึงตัวแปรและฟังก์ชันทั้งหมดที่กำหนดไว้ภายในฟังก์ชันภายนอกได้อย่างเต็มที่ (และตัวแปรและฟังก์ชันอื่น ๆ ทั้งหมดที่ฟังก์ชันภายนอกสามารถเข้าถึงได้) อย่างไรก็ตาม ฟังก์ชันภายนอกไม่สามารถเข้าถึงตัวแปรและฟังก์ชันที่กำหนดไว้ภายในฟังก์ชันภายในได้ นี่เป็นการห่อหุ้มตัวแปรของฟังก์ชันภายใน นอกจากนี้ เนื่องจากฟังก์ชันภายในสามารถเข้าถึงขอบเขตของฟังก์ชันภายนอกได้ ตัวแปรและฟังก์ชันที่กำหนดไว้ในฟังก์ชันภายนอกจะมีอายุการใช้งานนานกว่าระยะเวลาของการดำเนินการฟังก์ชันภายนอก หากฟังก์ชันภายในจัดการเพื่อให้อยู่รอดได้เกินอายุของฟังก์ชันภายนอก การทำงาน. การปิดจะถูกสร้างขึ้นเมื่อมีการสร้างฟังก์ชันภายในให้กับขอบเขตภายนอกฟังก์ชันภายนอก
Var pet = function(name) ( // ฟังก์ชั่นภายนอกกำหนดตัวแปรชื่อ "name" var getName = function() ( return name; // ฟังก์ชั่นภายในสามารถเข้าถึงตัวแปร "name" ของตัวแปรภายนอก //function ) return getName; // คืนฟังก์ชั่นภายในซึ่งจะเปิดเผยไปยังขอบเขตภายนอก ) myPet = pet("Vivie"); สัตว์เลี้ยงของฉัน(); // ส่งกลับ "วิวี่"
อาจซับซ้อนกว่าโค้ดด้านบนมาก อ็อบเจ็กต์ที่มีวิธีการจัดการตัวแปรภายในของฟังก์ชันภายนอกสามารถส่งคืนได้
Var createPet = function(name) ( var sex; return ( setName: function(newName) ( name = newName; ), getName: function() ( return name; ), getSex: function() ( return sex; ), setSex: ฟังก์ชั่น(newSex) ( if(typeof newSex === "string" && (newSex.toLowerCase() === "male" || newSex.toLowerCase() === "Female")) ( sex = newSex; ) ) ) ) var pet = createPet("Vivie"); pet.getName(); // Vivie pet.setName("โอลิเวอร์"); pet.setSex("ชาย"); สัตว์เลี้ยง.getSex(); // ตัวผู้ pet.getName(); //โอลิเวอร์
ในโค้ดข้างต้น ตัวแปรชื่อของฟังก์ชันภายนอกสามารถเข้าถึงได้โดยฟังก์ชันภายใน และไม่มีวิธีอื่นในการเข้าถึงตัวแปรภายในยกเว้นผ่านฟังก์ชันภายใน ตัวแปรภายในของฟังก์ชันภายในทำหน้าที่เป็นที่เก็บที่ปลอดภัยสำหรับอาร์กิวเมนต์และตัวแปรภายนอก พวกเขาเก็บข้อมูล "ถาวร" และ "ห่อหุ้ม" เพื่อให้ฟังก์ชันภายในใช้งานได้ ไม่จำเป็นต้องกำหนดฟังก์ชันให้กับตัวแปรหรือมีชื่อด้วยซ้ำ
Var getCode = (function() ( var apiCode = "0]Eal(eh&2"; // โค้ดเราไม่ต้องการให้บุคคลภายนอกสามารถแก้ไขได้... return function() ( return apiCode; ); ))() ; getCode(); // ส่งคืน apiCode
อย่างไรก็ตาม มีข้อผิดพลาดหลายประการที่ต้องระวังเมื่อใช้การปิด หากฟังก์ชันปิดล้อมกำหนดตัวแปรที่มีชื่อเดียวกันกับชื่อของตัวแปรในขอบเขตภายนอก จะไม่มีทางอ้างถึงตัวแปรในขอบเขตภายนอกได้อีก
Var createPet = function(name) ( // ฟังก์ชั่นภายนอกกำหนดตัวแปรชื่อ "name" return ( setName: function(name) ( // ฟังก์ชั่นที่แนบมายังกำหนดตัวแปรชื่อ "name" อีกด้วย name = name; // เราจะเข้าถึง "ชื่อ" ที่กำหนดโดยฟังก์ชันภายนอกได้อย่างไร ) ) )
การใช้วัตถุอาร์กิวเมนต์
อาร์กิวเมนต์ของฟังก์ชันจะถูกเก็บรักษาไว้ในวัตถุที่มีลักษณะคล้ายอาร์เรย์ ภายในฟังก์ชัน คุณสามารถระบุอาร์กิวเมนต์ที่ส่งไปให้ฟังก์ชันได้ดังนี้:
อาร์กิวเมนต์[i]
โดยที่ i คือเลขลำดับของอาร์กิวเมนต์ โดยเริ่มต้นที่ศูนย์ ดังนั้น อาร์กิวเมนต์แรกที่ส่งไปยังฟังก์ชันจะเป็นอาร์กิวเมนต์ จำนวนอาร์กิวเมนต์ทั้งหมดระบุโดย arguments.length
การใช้อ็อบเจ็กต์อาร์กิวเมนต์ คุณสามารถเรียกใช้ฟังก์ชันที่มีอาร์กิวเมนต์มากกว่าที่ประกาศอย่างเป็นทางการให้ยอมรับได้ สิ่งนี้มักจะมีประโยชน์หากคุณไม่ทราบล่วงหน้าว่าจะมีการส่งอาร์กิวเมนต์จำนวนเท่าใดไปยังฟังก์ชัน คุณสามารถใช้ arguments.length เพื่อกำหนดจำนวนอาร์กิวเมนต์ที่ส่งไปยังฟังก์ชันจริง จากนั้นจึงเข้าถึงแต่ละอาร์กิวเมนต์โดยใช้อ็อบเจ็กต์อาร์กิวเมนต์
ตัวอย่างเช่น พิจารณาฟังก์ชันที่เชื่อมหลายสตริงเข้าด้วยกัน อาร์กิวเมนต์ที่เป็นทางการเพียงอย่างเดียวสำหรับฟังก์ชันนี้คือสตริงที่ระบุอักขระที่แยกรายการที่จะต่อกัน ฟังก์ชั่นถูกกำหนดดังนี้:
ฟังก์ชั่น myConcat(separator) ( var result = ""; // เริ่มต้นรายการ var i; // วนซ้ำอาร์กิวเมนต์สำหรับ (i = 1; i< arguments.length; i++) { result += arguments[i] + separator; } return result; }
คุณสามารถส่งผ่านอาร์กิวเมนต์จำนวนเท่าใดก็ได้ไปยังฟังก์ชันนี้ และมันจะเชื่อมแต่ละอาร์กิวเมนต์เข้ากับสตริง "list":
// ส่งกลับ "แดง, ส้ม, น้ำเงิน, " myConcat(", ", "red", "orange", "blue"); // ส่งคืน "elephant; giraffe; lion; cheetah; " myConcat("; ", "elephant", "giraffe", "lion", "cheetah"); // ส่งกลับ "sage. basil. oregano.pepper. parsley. " myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
บันทึก:ตัวแปรอาร์กิวเมนต์คือ "เหมือนอาร์เรย์" แต่ไม่ใช่อาร์เรย์ มันเหมือนกับอาเรย์ตรงที่มีดัชนีตัวเลขและคุณสมบัติความยาว อย่างไรก็ตาม มันไม่มีวิธีการจัดการอาเรย์ทั้งหมด
ปัจจัยสองประการที่มีอิทธิพลต่อการใช้ฟังก์ชันลูกศร ได้แก่ ฟังก์ชันที่สั้นลงและการไม่ผูกมัดฟังก์ชันนี้
ฟังก์ชั่นที่สั้นกว่า
ในรูปแบบการทำงานบางรูปแบบ เรายินดีต้อนรับฟังก์ชันที่สั้นกว่า เปรียบเทียบ:
Var a = [ "ไฮโดรเจน", "ฮีเลียม", "ลิเธียม", "เบริลเลียม" ]; var a2 = a.map(function(s) ( return s.length; )); console.log(a2); // บันทึก var a3 = a.map(s => s.length); console.log(a3); // บันทึก
ไม่แยกอันนี้.
จนกระทั่งลูกศรทำงาน ฟังก์ชันใหม่ทุกฟังก์ชันจะกำหนดค่าของตัวเอง (วัตถุใหม่ในกรณีของตัวสร้าง ไม่ได้กำหนดไว้ในการเรียกฟังก์ชัน วัตถุฐานหากฟังก์ชันถูกเรียกว่า "วิธีวัตถุ" ฯลฯ ) สิ่งนี้ได้รับการพิสูจน์แล้วว่าน้อยกว่าอุดมคติด้วยรูปแบบการเขียนโปรแกรมเชิงวัตถุ
Function Person() ( // ตัวสร้าง Person() กำหนด `this` ในตัวมันเอง this.age = 0; setInterval(function growUp() ( // ในโหมดไม่เข้มงวด ฟังก์ชัน growUp() จะกำหนด `this` // เป็น global object ซึ่งแตกต่างจาก `this` // ที่กำหนดโดย Person() Constructor. this.age++; ), 1000); ) var p = new Person();
ใน ECMAScript 3/5 ปัญหานี้ได้รับการแก้ไขแล้วโดยการกำหนดค่าในสิ่งนี้ให้กับตัวแปรที่สามารถปิดได้
Function Person() ( var self = this; // บางคนเลือก `that` แทนที่จะเป็น `self`. // เลือกหนึ่งอย่างและสอดคล้องกัน self.age = 0; setInterval(function growUp() ( // การเรียกกลับหมายถึง ตัวแปร `self` ซึ่ง // ค่าเป็นวัตถุที่คาดหวัง self.age++; ), 1000); )