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



javascript เบื้องต้น บทที่ ๙: การใช้งานออบเจ็กต์
เขียนเมื่อ 2019/07/31 23:16
แก้ไขล่าสุด 2021/09/28 16:42

ตั้งแต่ในบทที่ ๓ ได้เริ่มเขียนแนะนำข้อมูลชนิดต่างๆไปแล้ว และได้แนะนำเกี่ยวกับข้อมูลชนิดที่เรียกว่า "ออบเจ็กต์" (object) ไป

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



การสร้างออบเจ็กต์

ออบเจ็กต์ คือข้อมูลโครงสร้างที่ประกอบไปด้วยค่าต่างๆเก็บไว้ภายใน เรียกว่า "พรอเพอร์ตี" (property)

แต่ละพรอเพอร์ตีจะมีการตั้งชื่อเรียกเพื่อเข้าถึง ชื่อนั้นเรียกว่า "คีย์" (key)

การสร้างทำได้ง่ายๆโดยใช้วงเล็บปีกกา {} แล้วใส่คีย์ ตามด้วยทวิภาค (colon) : ตามด้วยค่าพรอเพอร์ตี โดยพรอเพอร์ตีแต่ละตัวจะคั่นด้วยจุลภาค (comma) ,

ตัวอย่าง
var pokemon1 = {
  chue: "ฟุชิงิดาเนะ",
  sung: 0.7,
  nak: 6.9
};
(ภาพฟุชิงิดาเนะ ที่มา)

แบบนี้ก็จะได้ข้อมูลออบเจ็กต์ที่เป็น pokemon (โปเกมอน) ซึ่งมีพรอเพอร์ตีคือ chue (ชื่อ) ฟุชิงิดาเนะ sung (สูง) 0.7 และ nak (หนัก) 6.9

ปกติเวลาสร้างออบเจ็กต์นั้นบ่อยครั้งที่เขียนแยกพรอเพอร์ตีแต่ละตัวไว้เขียนคนละบรรทัดแบบนี้เพื่อให้เข้าใจง่าย

แต่ที่จริงจะเขียนต่อกันทีเดียวในบรรทัดเดียวก็ทำได้ เช่น
var pokemon1 = {chue: "ฟุชิงิดาเนะ", sung: 0.7, nak: 6.9};

ที่สำคัญคือให้คั่นคีย์กับค่าพรอเพอร์ตีด้วยโคลอน : และคั่นระหว่างแต่ละพรอเพอร์ตีด้วยจุลภาค ,

หลังพรอเพอร์ตีตัวสุดท้ายไม่จำเป็นต้องใส่จุลภาค แต่จะใส่ก็ได้ไม่ผิด
var pokemon1 = {chue: "ฟุชิงิดาเนะ", sung: 0.7, nak: 6.9,};

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

หากต้องการสร้างออบเจ็กต์ว่างเปล่าที่ไม่มีพรอเพอร์ตีอะไรเลยก็ทำได้ แบบนั้นก็แค่ใส่วงเล็บปีกกาเปิดปิดไว้เฉยๆ
var wangplao = {};

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

เช่น
var pokemon2 = {
  "chue": "พีคาชู",
  "chue len": "พีคา",
  "suan-sung": 0.4,
  "nam-nak-tua": 6.0
};

ในตัวอย่างนี้ เฉพาะ chue (ชื่อ) เท่านั้นที่ไม่จำเป็นต้องใส่เครื่องหมายคำพูดคร่อมก็ได้ แต่ว่าจะใส่ไว้ก็ได้ แล้วแต่

ส่วน chue len (ชื่อเล่น) มีเว้นวรรค และ suan-sung (ส่วนสูง) และ nam-nak-tua (น้ำหนักตัว) มีขีด - อยู่ดังนั้นต้องใส่เครื่องหมายคำพูด ไม่เช่นนั้นจะเกิดข้อผิดพลาด



การเข้าถึงข้อมูลในออบเจ็กต์

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

ขอยกตัวอย่างด้วย pokemon2 ที่สร้างขึ้นจากหัวข้อที่แล้ว เช่นเมื่อต้องการดูข้อมูล chue (ชื่อ)
alert(pokemon2.chue); // ได้ พีคาชู

หรืออาจเข้าถึงค่าโดยใส่วงเล็บเหลี่ยม แล้วใส่คีย์ไว้ด้านใน กรณีนี้จะต้องใส่เครื่องหมายคำพูดเสมอ
alert(pokemon2["chue"]); // ได้ พีคาชู

แต่สำหรับพรอเพอร์ตีที่ตั้งคีย์เป็นคำที่มีพวกเครื่องหมายหรือเว้นวรรคจะใช้วิธีแรกในการเข้าถึงไม่ได้ ต้องใช้วงเล็บเหลี่ยมเท่านั้น
alert(pokemon2["chue len"]); // ได้ พีคา
alert(pokemon2["suan-sung"]); // ได้ 0.4

นอกจากนี้ หากคีย์ขึ้นต้นด้วยตัวเลขก็ไม่สามารถเข้าถึงโดยใช้จุดเช่นกัน เพียงแต่สำหรับตัวเลขจะใส่เครื่องหมายคำพูดหรือไม่ก็ได้
var h = {1: "a", 2: "b"};
alert(h[1]); // ได้ a
alert(h["2"]); // ได้ b

คีย์ถือเป็นข้อมูลชนิดสายอักขระเสมอ แม้ต่อให้ตอนที่ประกาศชื่อคีย์จะใส่เป็นตัวเลขไปก็จะได้สายอักขระที่เป็นตัวเลข ดังนั้นในที่นี้คีย์ไม่ใช่ตัวเลข 1 แต่เป็นสายอักขระ "1"

เพียงแต่ถ้าใส่ตัวเลข 1 ไปเฉยๆจะถูกตีความเป็นสายอักขระให้ จึงใช้เข้าถึงพรอเพอร์ตีได้เช่นกัน

ถ้าใส่ชื่อพรอเพอร์ตีที่ไม่มีอยู่จะได้ undefined
var obji = {a: 1};
alert(obji.b); // ได้ undefined

สิ่งที่ใส่ใน [ ] อาจเป็นตัวแปรที่เก็บค่าสายอักขระก็ได้ เช่น
var obja = {b: 5};
var prop = "b";
alert(obja[prop]); // ได้ 5

กรณีนี้ obja[prop] ไม่ได้หมายถึงหาพรอเพอร์ตีที่ชื่อ prop แต่หมายถึงให้หาพรอเพอร์ตีที่ชื่อมีค่าตามที่อยู่ในตัวแปร prop นั่นก็คือ b นั่นเอง

แต่ถ้าใส่เครื่องหมายคำพูดกลายเป็น obja["prop"] แบบนี้ จะมีค่าเท่ากับการเขียน obja.prop นั่นคือให้หาพรอเพอร์ตีที่ชื่อ prop ซึ่งในเมื่อไม่ได้กำหนดไว้ก็จะได้ undefined
alert(obja["prop"]); // ได้ undefined

ดังนั้นจะเห็นว่าการใส่เครื่องหมายคำพูดคร่อมหรือไม่นั้นสำคัญ ต้องระวังสับสนแล้วใช้ผิด



การเพิ่มหรือแก้ข้อมูลในออบเจ็กต์

การเพิ่มพรอเพอร์ตีให้กับออบเจ็กต์สามารถทำได้โดยวิธีการที่คล้ายกับตอนดูค่า นั่นคือใช้จุดหรือวงเล็บเหลี่ยม
var pokemon3 = {
  lek: 111,
  lv: 30
};
pokemon3.chue = "ไซฮอร์น"; // เพิ่มพรอเพอร์ตี chue (ชื่อ)
pokemon3["nak"] = 115; // เพิ่มพรอเพอร์ตี nak (หนัก)
alert(pokemon3["chue"]); // ได้ ไซฮอร์น
alert(pokemon3.nak); // ได้ 115

ถ้าหากเป็นพรอเพอร์ตีที่มีอยู่แล้วจะเป็นการแก้ค่านั้น ไม่ได้สร้างพรอเพอร์ตีใหม่ขึ้น
pokemon.lv = 34; // แก้ lv



ออบเจ็กต์ในออบเจ็กต์

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

ตัวอย่าง
phulen = {
  chue: "ซาโตชิ",
  pk1: {
    chue: "พีคาชู",
    lv: 98
  },
  pk2: {
    chue: "ลิซาร์ดอน",
    lv: 40
  }
};

โครงสร้างเวลาสร้างอาจดูซับซ้อนขึ้นสักหน่อย แต่ว่าโดยปกติแล้วจะอาศัยการเคาะวรรคให้ร่นเข้าไปอีกขั้นเพื่อให้เข้าใจว่านี่เป็นโครงสร้างที่อยู่ลึกเข้าไปด้านในอีก ช่วยให้เข้าใจได้ง่ายขึ้น ลดการสับสน

เวลาสร้างออบเจ็กต์ซ้อนในออบเจ็กต์แบบนี้ เพื่อให้ดูง่ายขึ้นอาจเตรียมค่าเอาไว้ในตัวแปรนึงก่อนแล้วค่อยเอาตัวแปรนั้นมาใส่ลงในออบเจ็กต์หลัก

เช่นตัวอย่างข้างต้นอาจเขียนแบบนี้ได้ จะได้ผลเหมือนเดิม
chue = "ซาโตชิ";
pk1 = {
  chue: "พีคาชู",
  lv: 98
};
pk2 = {
  chue: "ลิซาร์ดอน",
  lv: 40
};
phulen = {
  chue: chue,
  pk1: pk1,
  pk2: pk2
};

นอกจากนี้ อาจสร้างออบเจ็กต์เปล่าเตรียมไว้แล้วค่อยๆป้อนพรอเพอร์ตีให้ก็ได้
phulen = {};
phulen.chue = "ซาโตชิ";
phulen.pk1 = {
  chue: "พีคาชู",
  lv: 98
};
phulen.pk2 = {
  chue: "ลิซาร์ดอน",
  lv: 40
};

จะเห็นวิธีการสร้างมีอยู่หลากหลาย สามารถเลือกใช้ตามที่สะดวกได้

ส่วนการจะเข้าถึงข้อมูลที่อยู่ในออบเจ็กต์ด้านในก็อาจทำได้โดยการเขียนจุดต่อกันไปเลย หรือจะใช้วงเล็บเหลี่ยมต่อกัน หรือปนกันก็ได้
alert(phulen.pk1.chue); // ได้ พีคาชู
alert(phulen["pk2"]["chue"]); // ได้ ลิซาร์ดอน
alert(phulen["pk1"].lv); // ได้ 98
alert(phulen.pk2["lv"]); // ได้ 40
alert(phulen.chue); // ได้ ซาโตชิ

จะเอาออบเจ็กต์ข้างในมาเก็บในตัวแปรอีกตัวก่อนแล้วค่อยเข้าถึงพรอเพอร์ตีข้างในอีกทีก็ได้
var pk = phulen.pk1;
alert(pk.chue); // ได้ พีคาชู



ออบเจ็กต์และตัวแปรที่เก็บออบเจ็กต์

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

ความหมายก็คือ สมมุติว่าเราสร้างออบเจ็กต์ป้อนให้ตัวแปรนึง จากนั้นเราเอาค่าตัวแปรนั้นไปป้อนให้ตัวแปรอื่นอีก
var pokemon3 = {lv: 15};
var pokemonx = pokemon3;

จะได้ว่าตัวแปรทั้ง ๒ ตัวนั้นชี้ไปที่ออบเจ็กต์ตัวเดียวกัน ค่าพรอเพอร์ตีของข้อมูลภายในออบเจ็กต์นั้นจะเข้าถึงผ่านตัวแปรไหนก็ได้เหมือนกัน
alert(pokemon3.lv); // ได้ 15
alert(pokemonx.lv); // ได้ 15

และหากมีการเปลี่ยนแปลงค่าพรอเพอร์ตีในนั้น ความเปลี่ยนแปลงก็จะเกิดขึ้นกับทั้งสองตัวแปร เพราะถือเป็นตัวเดียวกัน
pokemonx.lv = 17; // แก้ค่า lv
alert(pokemonx.lv); // ได้ 17
alert(pokemon3.lv); // ได้ 17

เพียงแต่ระวังสับสน ที่ว่าจะเปลี่ยนแปลงไปพร้อมกันนั้นคือเฉพาะเมื่อมีการแก้พรอเพอร์​ตีเท่านั้น แต่หากมีการป้อนค่าแทนเข้าไปที่ตัวแปรนั้นใหม่โดยตรง ตัวแปรนั้นจะไปเก็บข้อมูลใหม่แทน และไม่มีอะไรเกี่ยวข้องกับออบเจ็กต์ที่เคยอยู่กับตัวแปรนั้นอีก ตัวแปรอีกตัวที่ไม่ได้ถูกแทนก็จะอยู่เหมือนเดิม และต่อให้ทำอะไรอีกก็ไม่เกี่ยวข้องกันแล้ว
pokemonx = {lv: 21}; // เอาออบเจ็กต์ใหม่แทนลงตัวแปรเดิม
alert(pokemonx.lv); // ได้ 21
alert(pokemon3.lv); // ได้ 17
pokemon3.lv = 23;
alert(pokemon3.lv); // ได้ 23
alert(pokemonx.lv); // ได้ 21

ตรงนี้อาจเข้าใจยากและชวนสับสนสักหน่อย อาจต้องใช้เวลาคิดและทำความเข้าใจให้ดี

หากต้องการคัดลอกออบเจ็กต์โดยไม่ได้ต้องการให้เป็นออบเจ็กต์เดียวกัน อาจต้องทำแบบนี้
var pk1 = { chue: "ฮิโตคาเงะ", lv: 14 }; // ออบเจ็กต์ต้นฉบับ
var pk2 = { chue: pk1.chue, lv: pk1.chue }; // ออบเจ็กต์ที่คัดลอกมา

แต่ก็ดูแล้วยุ่งยาก เพราะต้องมาไล่เขียนพรอเพอร์ตีทีละตัวทั้งหมด

แต่ใน ES5 มีฟังก์ชันที่ช่วยทำให้คัดลอกออบเจ็กต์ได้อย่างสะดวก รายละเอียดอ่านในบทที่ ๒๘

หรืออย่างใน ES6 จะมีฟังก์ชัน Object.assign ซึ่งก็เป็นอีกวิธีที่ช่วยทำให้คัดลอกออบเจ็กต์ได้



การตรวจดูว่าออบเจ็กต์มีคีย์ที่ต้องการอยู่หรือไม่

ทำได้โดยใช้ in โดยใส่ชื่อคีย์ ตามด้วย in แล้วตามด้วยออบเจ็กต์นั้น
var obju = {
  a: 5,
  "100": "!!!"
};
alert("a" in obju); // ได้ true
alert("b" in obju); // ได้ false

กรณีที่คีย์เป็นตัวเลข จะใส่ในรูปสายอักขระหรือตัวเลขก็ได้
alert("100" in obju); // ได้ true
alert(100 in obju); // ได้ true



การลบพรอเพอร์ตีออกจากออบเจ็กต์

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

ตัวอย่าง
var obra = {k: 10};
alert(obra.k); // ได้ 10
alert("k" in obra); // ได้ true
delete obra.k; // ลบ
alert(obra.k); // ได้ undefined
alert("k" in obra); // ได้ false



ออบเจ็กต์คือโครงสร้างแถวลำดับแบบจับคู่

ในภาษาโปรแกรมต่างๆจะมีข้อมูลกลุ่มประเภทที่เรียกว่า "แถวลำดับแบบจับคู่" (associative array)

เพียงแต่ว่าในแต่ละภาษามีชื่อเรียกต่างกันไป เช่น

- ในภาษาไพธอน เรียกว่า "ดิกชันนารี" (dict)
- ในภาษารูบี เรียกว่า "แฮช" (hash)
- ในภาษา C++ เรียกว่า "โครงสร้างข้อมูล" (structure)

รายละเอียดก็อาจต่างกันออกไป แต่โดยรวมแล้วมีสิ่งที่เหมือนกันคือเป็นข้อมูลชนิดกลุ่ม ซึ่งประกอบด้วยข้อมูลหลายๆอย่างอยู่ด้วยกัน โดยข้อมูลแต่ละตัวจะถูกตั้งชื่อไว้เพื่อใช้อ้างอิงได้เวลาที่ต้องการเข้าถึงข้อมูลในนั้น ชื่อที่ใช้เข้าถึงข้อมูลนั้นเรียกว่า "คีย์" (key)

ปกติเวลาเข้าถึงข้อมูลในแถวลำดับแบบจับคู่จะทำได้โดยเขียน ["คีย์"] แบบนี้ต่อท้าย

และในภาษาที่มีแนวคิดการเขียนโปรแกรมเชิงวัตถุ (OOP) โดยทั่วไปจะมีสิ่งที่เรียกว่าเป็น "ออบเจ็กต์" คือเป็น "วัตถุ" ในออบเจ็กต์จะประกอบไปด้วยสิ่งที่เรียกว่า "พรอเพอร์ตี" (property) หรือในบางภาษาอาจเรียกว่า "แอตทริบิวต์" (attribute) แต่ในจาวาสคริปต์มักใช้คำว่าพรอเพอร์ตี ที่จริงมักจะหมายถึงสิ่งเดียวกันหรือใกล้เคียงกัน

ซึ่งเวลาเข้าถึงข้อมูลในพรอเพอร์ตีจะเขียนในรูป .ชื่อพรอเพอร์ตี แบบนี้

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

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

ดังนั้น ออบเจ็กต์ในจาวาสคริปต์นั้นเป็นทั้งออบเจ็กต์และเป็นทั้งแถวลำดับแบบจับคู่ไปในตัว

ในขณะที่ในภาษาอื่นเช่นไพธอนหรือรูบีนั้น ออบเจ็กต์ กับ แถวลำดับแบบจับคู่ (ในไพธอนเรียก "ดิกชันนารี" ในรูบีเรียก "แฮช") ถือเป็นคนละสิ่งกัน แม้จะมีส่วนคล้าย แต่อะไรหลายอย่างแตกต่างกันมาก

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




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

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

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

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> 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月

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

ไทย

日本語

中文