φυβλαςのβλογ
บล็อกของ phyblas



javascript เบื้องต้น บทที่ ๒๓: การวนซ้ำด้วย for๛in
เขียนเมื่อ 2019/07/31 23:37
แก้ไขล่าสุด 2024/03/28 23:05


การวนซ้ำพรอเพอร์ตีในออบเจ็กต์ด้วย for๛in

ในบทที่ ๘ ได้เขียนถึงเรื่องการเขียนโปรแกรมให้มีการวนซ้ำโดยใช้ for และ while ไปแล้ว

แต่นอกจากนั้นแล้วยังมีอีกวิธีที่สามารถทำได้ คือวิธีการที่เรียกว่า for๛in

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

for๛in นั้นจะทำได้ต่อเมื่อมีออบเจ็กต์ และออบเจ็กต์นั้นมีพรอเพอร์ตีอยู่

เราสามารถทำการวนซ้ำเพื่อไล่จัดการกับพรอเพอร์ตีในออบเจ็กต์ทีละตัวได้โดยใช้ for๛in วิธีการใช้เป็นดังนี้
for (var ชื่อตัวแปรที่จะรับคีย์ในแต่ละรอบ in ออบเจ็กต์) {
  สิ่งที่ต้องการทำ
}

ตัวอย่าง
var rakha = {
  soba: 100,
  ramen: 110,
  udon: 120
};
var s = "";

for (var ahan in rakha) {
  s += ahan + " ราคา " + rakha[ahan] + " บาท, ";
}
alert(s); // ได้ soba ราคา 100 บาท, ramen ราคา 110 บาท, udon ราคา 120 บาท,

จะเห็นว่าเมื่อใช้ for in แล้ว ตัวแปร ahan จะแทนคีย์ของออบเจ็กต์ทีละตัว รอบแรกแทน soba ต่อมาแทน rame แล้วก็ udon



การวนซ้ำในแถวลำดับด้วย for๛in

แถวลำดับก็เป็นออบเจ็กต์ชนิดหนึ่ง จึงสามารถใช้ for๛in เพื่อวนซ้ำได้ โดยเมื่อใช้ จะได้ค่า 0,1,2 ตามลำดับ
var ar = ["ก", "ข", "ค"];
alert(ar); // ได้ ก,ข,ค
for (var a in ar) {
  alert(a + ": " + ar[a]); // ได้ 0: ก, 1: ข, 2: ค ตามลำดับ
}

อย่างไรก็ตาม หากมีค่าระหว่างทางที่ไม่ได้ถูกป้อนค่าไว้ ก็จะไม่ได้ไล่เรียงเลขไปทั้งหมด แต่โดดข้าม
var kaeng = ["แกงเขียวหวาน", "แกงฮังเล"];
kaeng[5] = "แกงกะหรี่";
alert(kaeng); // ได้ แกงเขียวหวาน,แกงฮังเล,,,,แกงกะหรี่
var s = "";
for (var k in kaeng) {
  s += k + "~" + kaeng[k] + "] ";
}
alert(s); // ได้ 0~แกงเขียวหวาน] 1~แกงฮังเล] 5~แกงกะหรี่]

อีกทั้งแถวลำดับเองก็สามารถใส่พรอเพอร์ตีที่มีคีย์ที่ไม่ใช่ตัวเลขลงไปได้เช่นเดียวกับออบเจ็กต์ทั่วไป หากใส่ลงไปแล้ว เวลาใช้ for in แล้ว คีย์นั้นก็จะออกมาด้วย

ดังนั้นโดยทั่วไปแล้ว มักไม่นิยมใช้ for๛in ในการวนซ้ำของแถวลำดับ

เพียงแต่ว่าใน ES6 มีรูปแบบการวนซ้ำที่เรียกว่า for๛of เพิ่มเข้ามา วิธีนั้นนิยมใช้กับแถวลำดับ รายละเอียดเกี่ยวกับ for๛of ดูได้ที่บทที่ ๓๗ ซึ่งอยู่ในส่วนของเนื้อหา ES6

อนึ่ง หากใครใช้ภาษาไพธอนหรือรูบีมาจะพบว่ามีกาารวนซ้ำด้วย for๛in เหมือนกัน แต่ for๛in ของไพธอนและรูบีนั้นจะคล้ายกับ for๛of ของจาวาสคริปต์มากกว่า ต่างจาก for๛in ของจาวาสคริปต์ ดังนั้นระวังสับสน



พรอเพอร์ตีที่ใช้ใน for๛in ได้

จะเห็นว่า for๛in นั้นจะไล่เรียงพรอเพอร์ตีที่มีอยู่ในออบเจ็กต์ออกมา

แต่ว่าที่จริงแล้วออบเจ็กต์นั้นล้วนมีพรอเพอร์ตีติดตัวอยู่ เป็นสิ่งที่มีอยู่แล้วโดยไม่ได้ป้อนให้ เช่น .constructor หรือพวกเมธอดต่างๆอย่าง .hasOwnProperty

ส่วนในออบเจ็กต์ที่เป็นแถวลำดับนั้นก็มีพรอเพอร์ตีอย่าง .length และเมธอดอีกมากมายอย่าง .join, .sort, .push, ฯลฯ

ทั้งหมดนี้ล้วนเป็นพรอเพอร์ตี แต่เมื่อใช้ for๛in กลับไม่ถูกไล่เรียงออกมาด้วย

นั่นหมายความว่ามีพรอเพอร์ตีที่ใช้ for๛in ได้และไม่ได้อยู่

โดยทั่วไปแล้วพวกพรอเพอร์ตีและเมธอดส่วนหนึ่งที่มีอยู่ในตัวออบเจ็กต์ตั้งแต่แรกจะไม่ถูกไล่เรียงใน for๛in

นอกจากนี้ ออบเจ็กต์ในตัวของจาวาสคริปต์ เช่น Math เองก็ประกอบด้วยเมธอดและตัวแปรที่เป็นค่าคงที่ต่างๆมากมาย แต่ก็ไม่สามารถไล่เรียงใน for๛in ได้เช่นกัน

แต่ออบเจ็กต์พวกนี้ก็สามารถเพิ่มพรอเพอร์ตีลงไปได้เช่นกัน แล้วพรอเพอร์ตีนั้นก็ถูกไล่เรียงใน for๛in ได้ด้วย
Math.a = 0;
for (var m in Math) {
  alert(m); // ได้ a
}

จะได้ว่ามีแต่ a ที่ใส่เข้าไปใหม่เท่านั้นที่ปรากฏเมื่อใช้ for๛in

แต่แม้จะไม่ปรากฏใน for๛in แต่พรอเพอร์ตีพวกนี้ก็มีตัวตนอยู่จริง เมื่อใช้ in หรือ .hasOwnProperty ก็จะได้ true

เช่น PI ใน Math
alert("PI" in Math); // ได้ true
alert(Math.hasOwnProperty("PI")); // ได้ true



เมธอด propertyIsEnumerable

การตรวจสอบว่าพรอเพอร์ตีไหนปรากฏใน for๛in ได้ อาจใช้เมธอด propertyIsEnumerable

เมธอดนี้จะให้ค่า true เมื่อใส่ชื่อพรอเพอร์ตีที่ปรากฏใน for๛in ได้ และให้ false หากใส่ชื่อพรอเพอร์ตีที่ไล่เรียงใน for๛in ไม่ได้ หรือไม่มีอยู่

ตัวอย่าง
alert(Math.propertyIsEnumerable("PI")); // ได้ false
var obj = { a: 1 };
alert(obj.propertyIsEnumerable("a")); // ได้ true
var arr = ["ก", "ข", "ค"];
alert(arr.propertyIsEnumerable(1)); // ได้ true
alert(arr.propertyIsEnumerable(3)); // ได้ false
alert(arr.propertyIsEnumerable("length")); // ได้ false



พรอเพอร์ตีของโพรโทไทป์และออบเจ็กต์ที่รับทอด

หากมีการรับทอด หรือมีการใส่พรอเพอร์ตีลงไปให้โพรโทไทป์ พรอเพอร์ตีเหล่านั้นก็จะปรากฏใน for๛in ด้วยเช่นกัน

ตัวอย่าง
var Mew = function(chue) {
  this.chue = chue;
};
Mew.prototype.praphet = "เอสเปอร์";
Mew.prototype.namnak = 4.0;
var Mewtwo = function(chue, chuelen) {
  Mew.call(this, chue);
  this.chuelen = chuelen;
};
Mewtwo.prototype = new Mew();
Mewtwo.prototype.namnak = 127.0;
var mewtwo = new Mewtwo("มิวทู", "พระเจ้ามิวที่สอง");

var s = [];
for (var p in mewtwo) {
  s.push(p);
}
alert(s); // ได้ chue,chuelen,namnak,praphet

อย่างไรก็ตาม เมื่อมาลองใช้ propertyIsEnumerable ดูจะพบว่า เฉพาะพรอเพอร์ที่ถูกป้อนให้ตัวอินสแตนซ์โดยตรงเท่านั้นที่จะได้ true ส่วนพรอเพอร์ตีในโพรโทไทป์จะได้ false
alert(mewtwo.propertyIsEnumerable("chue")); // ได้ true
alert(mewtwo.propertyIsEnumerable("chuelen")); // ได้ true
alert(mewtwo.propertyIsEnumerable("praphet")); // ได้ false
alert(mewtwo.propertyIsEnumerable("namnak")); // ได้ false

ดังนั้นจะเห็นว่าพรอเพอร์ตีในโพรโทไทป์ก็สามารถปรากฏใน for๛in ได้ เพียงแต่ไม่สามารถตรวจสอบด้วย .propertyIsEnumerable ได้ เมธอดนี้สนเฉพาะพรอเพอร์ตีภายในตัวอินสแตนซ์เองเท่านั้น ใช้กับพรอเพอร์ตีในโพรโทไทป์ไม่ได้



พรอเพอร์ตีของออบเจ็กต์ global ในเบราว์เซอร์

ออบเจ็กต์ global นั้นมีพรอเพอร์ตีอยู่มากมาย และแต่ละอันนั้นสามารถปรากฏเมื่อใช้ for๛in

ลองไล่พรอเพอร์ตีของ global ในเบราว์เซอร์
var s = [];
for (k in this) {
  s.push(k);
}
alert(s.sort().join(" "));
ได้ผลลัพธ์ออกมามากมาย
InstallTrigger addEventListener alert applicationCache atob blur btoa caches cancelAnimationFrame cancelIdleCallback captureEvents clearInterval clearTimeout close closed confirm createImageBitmap crypto customElements devicePixelRatio dispatchEvent document dump event external fetch find focus frameElement frames fullScreen getComputedStyle getDefaultComputedStyle getSelection history indexedDB innerHeight innerWidth isSecureContext length localStorage location locationbar matchMedia menubar moveBy moveTo mozInnerScreenX mozInnerScreenY mozPaintCount name navigator onabort onabsolutedeviceorientation onafterprint onanimationcancel onanimationend onanimationiteration onanimationstart onauxclick onbeforeprint onbeforeunload onblur oncanplay oncanplaythrough onchange onclick onclose oncontextmenu oncuechange ondblclick ondevicelight ondevicemotion ondeviceorientation ondeviceproximity ondrag ondragend ondragenter ondragexit ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended onerror onfocus ongotpointercapture onhashchange oninput oninvalid onkeydown onkeypress onkeyup onlanguagechange onload onloadeddata onloadedmetadata onloadend onloadstart onlostpointercapture onmessage onmessageerror onmousedown onmouseenter onmouseleave onmousemove onmouseout onmouseover onmouseup onmozfullscreenchange onmozfullscreenerror onoffline ononline onpagehide onpageshow onpause onplay onplaying onpointercancel onpointerdown onpointerenter onpointerleave onpointermove onpointerout onpointerover onpointerup onpopstate onprogress onratechange onreset onresize onscroll onseeked onseeking onselect onselectstart onshow onstalled onstorage onsubmit onsuspend ontimeupdate ontoggle ontransitioncancel ontransitionend ontransitionrun ontransitionstart onunload onuserproximity onvolumechange onvrdisplayactivate onvrdisplayconnect onvrdisplaydeactivate onvrdisplaydisconnect onvrdisplaypresentchange onwaiting onwebkitanimationend onwebkitanimationiteration onwebkitanimationstart onwebkittransitionend onwheel open opener origin outerHeight outerWidth pageXOffset pageYOffset parent performance personalbar postMessage print prompt releaseEvents removeEventListener requestAnimationFrame requestIdleCallback resizeBy resizeTo s screen screenLeft screenTop screenX screenY scroll scrollBy scrollByLines scrollByPages scrollMaxX scrollMaxY scrollTo scrollX scrollY scrollbars self sessionStorage setInterval setResizable setTimeout sidebar sizeToContent speechSynthesis status statusbar stop toolbar top u2f updateCommands window

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




-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> javascript

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

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
ภาษา javascript
ภาษา mongol
ภาษาศาสตร์
maya
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

บทความแต่ละเดือน

2024年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2023年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2022年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2021年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2020年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

ค้นบทความเก่ากว่านั้น

ไทย

日本語

中文