บทความนี้นำเสนอความรู้ที่เกี่ยวข้องเกี่ยวกับ JavaScript โดยส่วนใหญ่จะแนะนำตัววนซ้ำส่วนหน้าของ JavaScript และตัวสร้างเครื่องมือสร้าง เพื่อนๆ ที่ต้องการจะอ้างอิงถึงมันได้ 
การเข้าสู่ Front-end (vue) สู่หลักสูตรการเรียนรู้: เข้าสู่การเรียนรู้
Iterator จัดเตรียมกลไกอินเทอร์เฟซแบบรวมเพื่อจัดเตรียมกลไกการเข้าถึงแบบรวมสำหรับโครงสร้างข้อมูลที่แตกต่างกันต่างๆ
การกำหนด Iterator คือการจัดหาเมธอด next() ให้กับอ็อบเจ็กต์ แต่ละครั้งที่เรียก next() ออบเจ็กต์ผลลัพธ์จะถูกส่งคืน โดยมีแอตทริบิวต์ 2 รายการ คือ value แสดงถึงค่าปัจจุบัน และ Done แสดงถึงว่าการข้ามผ่านเสร็จสมบูรณ์หรือไม่ .
ฟังก์ชั่น makeIterator (อาร์เรย์) {
ให้ดัชนี = 0;
กลับ {
ถัดไป: ฟังก์ชั่น () {
กลับ (
Array.length > ดัชนี ?
{value: อาร์เรย์[ดัชนี++]}:
{เสร็จสิ้น: จริง}
-
-
-
-
ให้ตัววนซ้ำ = makeIterator(['1','2'])
console.log(iterator.next()); // {ค่า: '1'}
console.log(iterator.next()); // {ค่า: '2'}
console.log(iterator.next()); // {เสร็จสิ้น: จริง}บทบาทของตัววนซ้ำ:
จัดเตรียมอินเทอร์เฟซการเข้าถึงแบบรวมและเรียบง่ายสำหรับโครงสร้างข้อมูลต่างๆ
ช่วยให้สมาชิกของโครงสร้างข้อมูลสามารถจัดเรียงตามลำดับที่แน่นอน
เพื่อการบริโภคโดยสำหรับ...ของ
ES6 จัดเตรียมคำสั่ง for of เพื่อสำรวจวัตถุตัววนซ้ำ เราจะใช้คำสั่ง for of เพื่อสำรวจตัววนซ้ำที่สร้างขึ้นด้านบน:
ให้ตัววนซ้ำ = makeIterator(['1','2'])
สำหรับ (ให้ค่าของตัววนซ้ำ) {
console.log(ค่า);
} // ตัววนซ้ำไม่สามารถวนซ้ำได้ผลลัพธ์คือข้อผิดพลาดที่แจ้งว่าตัววนซ้ำไม่สามารถทำซ้ำได้ เหตุใดจึงเป็นเช่นนั้น ES6 กำหนดว่าอินเทอร์เฟซ Iterator เริ่มต้นถูกปรับใช้ในคุณสมบัติ Symbol.iterator ของโครงสร้างข้อมูล หากโครงสร้างข้อมูลมีคุณสมบัติ Symbol.iterator โครงสร้างข้อมูลสามารถสำรวจได้
เราแปลงโฉม makeIterator แบบกำหนดเองดังนี้:
const MakeIterator = (อาร์เรย์) => ({
[สัญลักษณ์.ตัววนซ้ำ](){
ให้ดัชนี = 0;
กลับ {
ต่อไป(){
ให้ความยาว = Array.length;
ถ้า (ดัชนี < ความยาว) {
ส่งกลับ {ค่า: อาร์เรย์ [ดัชนี ++]}
}อื่น{
กลับ {เสร็จสิ้น: จริง}
-
-
-
-
-
สำหรับ (ให้ค่าของ MakeIterator([1,2])){
console.log(ค่า)
-
// 1
// 2เราเพิ่มเมธอด return ให้กับ MakeIterator หาก for...of ออกจากลูปก่อนกำหนด (โดยปกติจะเกิดจากข้อผิดพลาดหรือคำสั่งแบ่ง) เมธอด return() จะถูกเรียกเพื่อยุติการข้ามผ่าน
ตามคุณลักษณะนี้ หากออบเจ็กต์จำเป็นต้องล้างข้อมูลหรือปล่อยทรัพยากรก่อนที่จะเสร็จสิ้นการแวะผ่าน เราสามารถปรับใช้เมธอด return() และรวมการปิดไฟล์เมื่อการอ่านไฟล์ล้มเหลว
const MakeIterator = (อาร์เรย์) => ({
[สัญลักษณ์.ตัววนซ้ำ](){
ให้ดัชนี = 0;
กลับ {
ต่อไป(){
ให้ความยาว = Array.length;
ถ้า (ดัชนี < ความยาว) {
ส่งกลับ {ค่า: อาร์เรย์ [ดัชนี ++]}
}อื่น{
กลับ {เสร็จสิ้น: จริง}
-
-
กลับ(){
กลับ {เสร็จสิ้น: จริง}
-
-
-
-
สำหรับ (ให้ค่าของ MakeIterator([1, 2, 3])){
console.log(ค่า) // 1
// วิธีที่ 1
หยุดพัก;
// วิธีที่ 2
// โยนข้อผิดพลาดใหม่ ('ข้อผิดพลาด');
-อาร์เรย์
ชุด
แผนที่
วัตถุที่มีลักษณะคล้ายอาร์เรย์ เช่น วัตถุอาร์กิวเมนต์ วัตถุ DOM NodeList วัตถุ typedArray
// อาร์กิวเมนต์ฟังก์ชันวัตถุผลรวม () {
สำหรับ (ให้มูลค่าของการโต้แย้ง) {
console.log(ค่า)
-
-
ผลรวม(1,2)
// 1
// 2
// วัตถุ typedArray ให้ typeArry = ใหม่ Int8Array (2);
ประเภทArry[0] = 1;
ประเภทArry[1] = 2;
สำหรับ (ให้ค่าของ typeArry){
console.log(ค่า)
-
// 1
// 2วัตถุเครื่องกำเนิด
ฟังก์ชั่น*gen(){
ผลผลิต 1;
ผลผลิต 2;
-
สำหรับ (ให้ค่าของ gen()){
console.log(ค่า)
-สตริง
ถาม: เหตุใด Object จึงไม่มี Iterator ดั้งเดิม
ตอบ: สาเหตุที่ Object ไม่ปรับใช้อินเทอร์เฟซ Iterator ตามค่าเริ่มต้น เนื่องจากไม่แน่ใจว่าคุณสมบัติของอ็อบเจ็กต์ใดถูกสำรวจก่อน และคุณสมบัติใดถูกสำรวจในภายหลัง
โดยพื้นฐานแล้ว ทราเวอร์เซอร์เป็นกระบวนการเชิงเส้น สำหรับโครงสร้างข้อมูลที่ไม่ใช่เชิงเส้นใดๆ การใช้อินเทอร์เฟซทราเวอร์เซอร์จะเทียบเท่ากับการปรับใช้การแปลงเชิงเส้น
อย่างไรก็ตาม หากพูดอย่างเคร่งครัด อินเทอร์เฟซทราเวอร์เซอร์การปรับใช้วัตถุนั้นไม่จำเป็น เนื่องจากในขณะนี้วัตถุนั้นถูกใช้เป็นโครงสร้างแผนที่จริงๆ
งานทำลายล้าง
ให้ set = new Set().add('a').add('b').add('c');
ให้ [x,y] = ตั้งค่า; // x='a';ตัวดำเนินการแพร่กระจาย
var str = 'สวัสดี'; [...str] // ['h','e','l','l','o']
ตัวดำเนินการสเปรดเรียกอินเทอร์เฟซ Iterator ดังนั้น Object จึงไม่ปรับใช้อินเทอร์เฟซ Iterator ดังนั้นเหตุใดจึงสามารถใช้ตัวดำเนินการ...
เหตุผล: ตัวดำเนินการสเปรดมีสองประเภท
หนึ่งถูกใช้ในกรณีของพารามิเตอร์ฟังก์ชันและการขยายอาร์เรย์ ในกรณีนี้ วัตถุจะต้องทำซ้ำได้ (ทำซ้ำได้)
อีกอันหนึ่งใช้สำหรับการขยายอ็อบเจ็กต์ นั่นคือ {...obj} ในกรณีนี้ อ็อบเจ็กต์จะต้องนับได้ (นับได้)
ให้ obj1 = {
ชื่อ: 'เฉียนซุน'
-
ให้ obj2 = {
อายุ: 3
-
// อาร์เรย์อ็อบเจ็กต์สามารถนับได้ ให้ obj = {...obj1, ...obj2}
console.log(obj) //{ชื่อ: 'qianxun' อายุ: 3}
// วัตถุธรรมดาไม่สามารถทำซ้ำได้ตามค่าเริ่มต้น ให้ obj = [...obj1, ...obj2]
console.log(obj) // object ไม่สามารถทำซ้ำได้ ฟังก์ชั่น forOf (obj, cb) {
ให้ iteratorValue = obj[Symbol.iterator]();
ให้ผลลัพธ์ = iteratorValue.next()
ในขณะที่(!result.done){
cb(result.value)
ผลลัพธ์ = iteratorValue.next()
-
-
forOf([1,2,3], (ค่า)=>{
console.log(ค่า)
-
// 1
// 2
// 3ตามแนวคิด
ฟังก์ชันตัวสร้างเป็นโซลูชันการเขียนโปรแกรมแบบอะซิงโครนัสที่จัดทำโดย ES6 ฟังก์ชัน Generator เป็นเครื่องสถานะที่สรุปสถานะภายในหลายสถานะ
ฟังก์ชัน Generator ยังเป็นฟังก์ชันการสร้างอ็อบเจ็กต์ Traverser ซึ่งจะส่งคืนอ็อบเจ็กต์ Traverser หลังจากดำเนินการ
เป็นทางการ
1. มีเครื่องหมายดอกจันระหว่างคำสำคัญฟังก์ชันและชื่อฟังก์ชัน
2. นิพจน์ Yield ถูกใช้ภายในเนื้อหาของฟังก์ชันเพื่อกำหนดสถานะภายในต่างๆ
ฟังก์ชั่น * simpleGenerator () {
ผลผลิต 1;
ผลผลิต 2;
-
เครื่องกำเนิดไฟฟ้าแบบง่าย ()ดังที่กล่าวมาข้างต้น เราได้สร้าง Generator แบบง่ายๆ และเราสำรวจมันด้วยคำถามสองข้อ:
จะเกิดอะไรขึ้นหลังจากที่ฟังก์ชัน Generator ทำงาน?
นิพจน์ผลผลิตในฟังก์ชันทำอะไร?
ฟังก์ชั่น * simpleGenerator () {
console.log('สวัสดีชาวโลก');
ผลผลิต 1;
ผลผลิต 2;
-
ให้เครื่องกำเนิดไฟฟ้า = simpleGenerator(); // simpleGenerator {<suspended}}
console.log (เครื่องกำเนิดไฟฟ้าถัดไป ())
//สวัสดีชาวโลก
// {value: 1, เสร็จแล้ว: false}
console.log (เครื่องกำเนิดไฟฟ้าถัดไป ())
// {value: 2, เสร็จแล้ว: false}ฟังก์ชันตัวสร้างตัวสร้างส่งคืนอ็อบเจ็กต์ตัวสร้างหลังจากทำงาน ในขณะที่ฟังก์ชันธรรมดาจะรันโค้ดภายในฟังก์ชันโดยตรง แต่ละครั้งที่มีการเรียกใช้เมธอดถัดไปของอ็อบเจ็กต์ตัวสร้าง ฟังก์ชันจะถูกดำเนินการจนกว่าคีย์เวิร์ด Yield ถัดไปจะหยุดการดำเนินการ และ วัตถุ {value: Value, เสร็จแล้ว: Boolean}
นิพจน์ผลผลิตนั้นไม่มีค่าที่ส่งคืน หรือจะส่งกลับโดยไม่ได้กำหนดเสมอ วิธีถัดไปสามารถรับพารามิเตอร์ได้หนึ่งตัว ซึ่งจะถือเป็นค่าตอบแทนของนิพจน์ผลตอบแทนก่อนหน้า ด้วยพารามิเตอร์ของวิธีการถัดไปสามารถฉีดค่าที่แตกต่างกันจากภายนอกเข้าสู่ด้านในในขั้นตอนต่างๆ ของฟังก์ชัน Generator เพื่อปรับพฤติกรรมของฟังก์ชัน เนื่องจากพารามิเตอร์ของวิธีถัดไปแสดงถึงค่าที่ส่งคืนของนิพจน์ผลตอบแทนก่อนหน้า พารามิเตอร์ที่ส่งผ่านจึงไม่ถูกต้องในครั้งแรกที่ใช้วิธีถัดไป
ผลรวมฟังก์ชัน(x){
ฟังก์ชันส่งคืน (y) {
กลับ x + y;
-
-
console.log(ผลรวม(1)(2))
// ใช้พารามิเตอร์ถัดไปเพื่อเขียนฟังก์ชันใหม่* sum(x){
ให้ y = ให้ผลผลิต x;
ในขณะที่ (จริง) {
y = ผลผลิต x + y;
-
-
ให้ Gen = ผลรวม (2)
console.log(gen.next()) // 2
console.log(gen.next(1)) // 3
console.log(gen.next(2)) // 4บทบาทของการแสดงออกของผลผลิต: การกำหนดสถานะภายในและการหยุดการดำเนินการชั่วคราว ความแตกต่างระหว่างการแสดงออกของผลผลิตและคำสั่งส่งคืน
นิพจน์ Yield หมายความว่าฟังก์ชันหยุดการดำเนินการชั่วคราวและดำเนินการย้อนกลับจากตำแหน่งนั้นในครั้งต่อไปต่อไป ในขณะที่คำสั่ง Return ไม่มีฟังก์ชันของหน่วยความจำตำแหน่ง
ในฟังก์ชัน สามารถดำเนินการคำสั่ง return ได้เพียงคำสั่งเดียว แต่สามารถดำเนินการได้หลายนิพจน์ผลตอบแทน
ฟังก์ชันใดๆ สามารถใช้คำสั่ง return ได้ นิพจน์ Yield สามารถใช้ได้เฉพาะในฟังก์ชัน Generator เท่านั้น หากใช้ที่อื่นจะมีการรายงานข้อผิดพลาด
หากนิพจน์ผลตอบแทนมีส่วนร่วมในการดำเนินการ ให้ใส่ไว้ในวงเล็บ หากใช้เป็นพารามิเตอร์ฟังก์ชันหรือวางไว้ทางด้านขวาของนิพจน์การกำหนด วงเล็บอาจไม่รวมอยู่ด้วย
ฟังก์ชั่น *gen () {
console.log('สวัสดี' + ผลผลิต) ×
console.log('hello' + (ผลผลิต)) √
console.log('hello' + ผลตอบแทน 1) ×
console.log('hello' + (ผลผลิต 1)) √
ฟู(ผลผลิต 1) √
พารามิเตอร์ const = ผลผลิต 2 √
-จากข้อเท็จจริงที่ว่าฟังก์ชันตัวสร้างตัวสร้างสามารถรองรับอัตราผลตอบแทนได้หลายค่า เราสามารถใช้สถานการณ์สมมติที่ฟังก์ชันมีค่าส่งคืนหลายค่าได้:
ฟังก์ชั่น * gen (num1, num2) {
ผลผลิต num1 + num2;
ผลผลิต num1 - num2;
-
ให้ res = gen(2, 1);
console.log(res.next()) // {value: 3, เสร็จแล้ว: false}
console.log(res.next()) // {value: 1, เสร็จแล้ว: false}เนื่องจากฟังก์ชัน Generator เป็นฟังก์ชันการสร้างตัววนซ้ำ Generator จึงสามารถกำหนดให้กับคุณสมบัติ Symbol.iterator ของอ็อบเจ็กต์ได้ เพื่อให้อ็อบเจ็กต์มีอินเทอร์เฟซ Iterator รหัสการใช้งานตัวสร้างมีความกระชับมากขึ้น
ให้ obj = {
ชื่อ: 'เฉียนซุน'
อายุ: 3,
[Symbol.iterator]: ฟังก์ชั่น(){
ปล่อยให้สิ่งนั้น = สิ่งนี้;
ให้คีย์ = Object.keys (นั้น)
ให้ดัชนี = 0;
กลับ {
ถัดไป: ฟังก์ชั่น () {
ส่งคืนดัชนี <keys.length?
{value: that[keys[index++]], เสร็จแล้ว: false}:
{ค่า: ไม่ได้กำหนด เสร็จสิ้น: จริง}
-
-
-
-
สำหรับ (ให้ค่าของ obj){
console.log(ค่า)
-เครื่องกำเนิดไฟฟ้า:
ให้ obj = {
ชื่อ: 'เฉียนซุน'
อายุ: 3,
[Symbol.iterator]: ฟังก์ชั่น* (){
ให้คีย์ = Object.keys (สิ่งนี้)
สำหรับ (ให้ i=0; i<keys.length; i++){
ให้สิ่งนี้ [คีย์ [i]];
-
-
-
สำหรับ (ให้ค่าของ obj){
console.log(ค่า)
-เมธอด
return()สามารถคืนค่าที่กำหนดและยุติฟังก์ชันตัวสร้างการแวะผ่าน
ฟังก์ชั่น*gen() {
ผลผลิต 1;
ผลผลิต 2;
ผลผลิต 3;
-
var g = เจน();
g.next() // { ค่า: 1, เสร็จแล้ว: false }
// หากไม่มีการระบุพารามิเตอร์เมื่อเรียกใช้เมธอด return() แอตทริบิวต์ value ของค่าที่ส่งคืนจะไม่ได้กำหนดไว้
g.return('foo') // { ค่า: "foo" เสร็จแล้ว: true }
g.next() // { ค่า: ไม่ได้กำหนด, เสร็จแล้ว: จริง } หากมี try...finally code block ภายในฟังก์ชัน Generator และ try code block กำลังถูกดำเนินการ ดังนั้นเมธอด return() จะทำให้โค้ด block finally ถูกป้อนทันที หลังจากดำเนินการ ฟังก์ชันทั้งหมดจะสิ้นสุด
ฟังก์ชัน* ตัวเลข () {
ผลผลิต 1;
พยายาม {
ผลผลิต 2;
ผลผลิต 3;
} ในที่สุด {
ผลผลิต 4;
ผลผลิต 5;
-
ผลผลิต 6;
-
var g = ตัวเลข();
g.next() // { ค่า: 1, เสร็จแล้ว: false }
g.next() // { ค่า: 2, เสร็จแล้ว: false }
g.return(7) // { ค่า: 4 เสร็จแล้ว: false }
g.next() // { ค่า: 5, เสร็จแล้ว: false }
g.next() // { ค่า: 7, เสร็จแล้ว: จริง }หากคุณต้องการเรียกใช้ฟังก์ชันตัวสร้างอื่นภายในฟังก์ชันตัวสร้าง เราจำเป็นต้องดำเนินการสำรวจภายในเนื้อหาของฟังก์ชันเดิมด้วยตนเอง หากการเรียกใช้ฟังก์ชันซ้อนอยู่ในหลายระดับ การเขียนจะยุ่งยากและอ่านยาก
มอบหมายให้เครื่องกำเนิดไฟฟ้าอื่น
ฟังก์ชั่น* g1() {
ผลผลิต 2;
ผลผลิต 3;
-
ฟังก์ชั่น* g2() {
ผลผลิต 1;
ผลตอบแทน* g1();
ผลผลิต 4;
-
ตัววนซ้ำ const = g2();
console.log(iterator.next()); // { ค่า: 1, เสร็จแล้ว: false }
console.log(iterator.next()); // { ค่า: 2, เสร็จแล้ว: false }
console.log(iterator.next()); // { ค่า: 3, เสร็จแล้ว: false }
console.log(iterator.next()); // { ค่า: 4, เสร็จแล้ว: false }
console.log(iterator.next()); // { ค่า: ไม่ได้กำหนด เสร็จแล้ว: จริง }มอบหมายให้กับวัตถุที่สามารถทำซ้ำได้อื่น ๆ
ฟังก์ชั่น*gen(){
ผลผลิต* [1,2,3]
-
console.log(gen().next()) // {value: 1, เสร็จแล้ว: false}ฟังก์ชัน Generator ส่งคืนทราเวอร์เซอร์ ES6 กำหนดว่าทราเวอร์เซอร์นี้เป็นอินสแตนซ์ของฟังก์ชัน Generator และสืบทอดวิธีการบนออบเจ็กต์ Generator.prototype แต่ไม่สามารถรับคุณสมบัติของสิ่งนี้ได้เนื่องจากนี่คือออบเจ็กต์ส่วนกลางในขณะนี้ ไม่ใช่อินสแตนซ์ วัตถุ.
ฟังก์ชั่น*gen(){
นี่.a = 1
-
gen.prototype.say = ฟังก์ชั่น(){
console.log('สวัสดี')
-
ให้ obj = gen()
console.log(obj instanceof gen) // จริง
obj.say() //สวัสดี
obj.ถัดไป()
console.log(obj.a) //ไม่ได้กำหนดหากคุณต้องการเข้าถึงคุณสมบัติของอินสแตนซ์ เช่น ตัวสร้าง คุณสามารถแก้ไขสิ่งนี้เพื่อผูกเข้ากับ Generator.prototype
ฟังก์ชั่น*gen(){
นี่.a = 1
-
gen.prototype.say = ฟังก์ชั่น(){
console.log('สวัสดี')
-
ให้ obj = gen.call (gen.prototype)
console.log(obj instanceof gen) // จริง
obj.say() //สวัสดี
obj.ถัดไป()
console.log(obj.a) //1 ฟังก์ชั่น * StateMachine (สถานะ) {
ปล่อยให้การเปลี่ยนแปลง;
ในขณะที่ (จริง) {
ถ้า (การเปลี่ยนแปลง === "เพิ่มขึ้น"){
รัฐ++;
}else if(transition === "DECREMENT"){
สถานะ--;
-
การเปลี่ยนแปลง = สถานะผลผลิต;
-
-
ตัววนซ้ำ const = StateMachine (0);
console.log(iterator.next()); // 0
console.log(iterator.next('INCREMENT')); // 1
console.log(iterator.next('DECREMENT')); // 0