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



javascript เบื้องต้น บทที่ ๔๘: ฟังก์ชันเพิ่มเติมสำหรับออบเจ็กต์
เขียนเมื่อ 2020/05/15 00:58
แก้ไขล่าสุด 2021/09/28 16:42

ใน ES6 ได้เพิ่มฟังก์ชัน (หรือเรียกว่าเป็นคลาสเมธอด) ในออบเจ็กต์ Object มาหลายตัว ในบทนี้จะแนะนำฟังก์ชันที่เพิ่มเข้ามาเหล่านั้น

สำหรับฟังก์ชันต่างๆที่เพิ่มเข้ามาตั้งแต่ ES5 แล้วดูได้ใน บทที่ ๒๕ และ บทที่ ๒๖




Object.assign

Object.assign ใช้รวมพรอเพอร์ตีในออบเจ็กต์ ๒ ตัวขึ้นไปเข้าด้วยกัน โดยเอาพรอเพอร์ตีจากตัวอื่นๆมาแจกให้กับตัวที่ต้องการ
Object.assign(ออบเจ็กต์ที่จะรับพรอเพอร์ตี, ออบเจ็กต์ที่จะให้พรอเพอร์ตี, ...)

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

ตัวอย่าง
let suanSiri = { mamuang: 30, taengmo: 20 };
let suanSutrit = { lamyai: 15 };
let suanSanchai = { som: 45, kluai: 300 };

Object.assign(suanSiri, suanSutrit, suanSanchai);
// suanSiri กลายเป็น { mamuang: 30, taengmo: 20, lamyai: 15, som: 45, kluai: 300 };

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

หากต้องการสร้างออบเจ็กต์ตัวใหม่ก็อาจใส่ตัวแรกเป็นออบเจ็กต์เปล่า {} แล้วรับเอาตัวออบเจ็กต์ที่คืนกลับจากฟังก์ชันนี้
let suanKitti = { kaeomangkon: 5, lamut: 35 };
let suanPiti = { thurian: 15, sapparot: 30};

let suanMai = Object.assign({}, suanKitti, suanPiti);
// ได้ suanMai เป็น { kaeomangkon: 5, lamut: 35, thurian: 15, sapparot: 30 }

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

ตัวที่ใส่เป็นตัวแรกนั้นถ้าไม่ใช่ออบเจ็กต์ก็จะถูกสร้างเป็นออบเจ็กต์ขึ้นมา เช่นถ้าใช้กับตัวเลขก็จะกลายเป็นออบเจ็กต์ตัวเลข คือใช้ได้เหมือนตัวเลขธรรมดา แต่มีพรอเพอร์ตีเพิ่มเติมอยู่ในตัวด้วย
let n = Object.assign(111, {x: 2});
alert(n); // ได้ 111
alert(typeof n); // ได้ object
alert(n.x); // ได้ 2

เพียงแต่กรณีแบบนี้สิ่งที่ได้จะเป็นออบเจ็กต์ใหม่ ไม่ได้ถูกทับลงในตัวแปรเก่า ตัวแปรเก่าก็จะยังเป็นตัวเดิม ต้องใช้ตัวแปรอีกตัวมารับออบเจ็กต์ตัวใหม่ที่ได้นี้
let n = 112;
alert(n === Object.assign(n, { x: 7 })); // ได้ false
let obj = {};
alert(obj === Object.assign(obj, { x: 7 })); // ได้ true

ฟังก์ชันนี้ยังถูกใช้เพื่อคัดลอกออบเจ็กต์ สร้างออบเจ็กต์ที่หน้าตาเหมือนกันแต่เป็นคนละตัวกันขึ้นมาอีกตัว โดยเขียนแบบนี้
let raiA = {khao: 20, thua: 30};
let raiB = Object.assign({}, raiA);
alert(raiA===raiB); // ได้ false (เพราะถือเป็นคนละออบเจ็กต์กัน)
alert(raiB.khao); // ได้ 20
alert(raiB.thua); // ได้ 30

แต่มีข้อควรระวัง คือเมื่อพรอเพอร์ตีในออบเจ็กต์เองก็เป็นออบเจ็กต์ด้วย แบบนี้จะไม่ใช่การคัดลอกอย่างสมบูรณ์ เพราะออบเจ็กต์ด้านในจะยังเป็นตัวเดียวกันอยู่
let Sanphon = {
  suanSom: {som: 200}
};
let Kamphon = Object.assign({}, Sanphon);

alert(Kamphon === Sanphon); // ได้ false (เป็นออบเจ็กต์คนละตัวกัน)
alert(Kamphon.suanSom === Sanphon.suanSom); // ได้ true (เป็นออบเจ็กต์ตัวเดียวกัน)

หากต้องการจะคัดลอกออบเจ็กต์ให้เป็นตัวใหม่ทั้งหมดแม้แต่เนื้อใน แบบนั้นควรใช้ JSON.parse กับ JSON.stringify แบบที่เขียนถึงในบทที่ ๒๘




Object.is

ฟังก์ชัน Object.is ใช้ดูว่าค่า ๒ ตัวเท่ากันหรือไม่ คล้ายการใช้ === ในการเปรียบเทียบ
alert(Object.is("ผงขาว", "แป้ง")); // ได้ false
alert(Object.is('แป้ง', "แป้ง")); // ได้ true
alert(Object.is({}, {})); // ได้ false

แต่มีข้อแตกต่างจาก === อยู่บ้าง ในกรณีที่ใช้กับ NaN หรือ 0 โดย Object.is จะถือว่า +0 และ -0 เป็นคนละตัวกัน และถือว่า NaN ทั้งหมดเป็นตัวเดียวกัน
alert(+0 === -0); // ได้ true
alert(Object.is(+0, -0)); // ได้ false

alert(NaN === NaN); // ได้ false
alert(Object.is(NaN, NaN)); // ได้ true




Object.setPrototypeOf

Object.setPrototypeOf ใช้ตั้งออบเจ็กต์ตัวหนึ่งให้เป็นโพรโทไทป์ของอีกตัวหนึ่ง

เรื่องของโพรโทไทป์ได้เขียนถึงในบทที่ ๒๑ นอกจากนี้ใน ES5 มีฟังก์ชันคล้ายๆกันคือ Object.getPrototypeOf สำหรับดูตัวโพรโทไทป์ของออบเจ็กต์ กล่าวถึงไปในบทที่ ๒๖

วิธีใช้
Object.setPrototypeOf(ออบเจ็กต์, ออบเจ็กต์ที่จะเป็นโพรโทไทป์)

ตัวอย่าง
let mot = {kha: 6};
let motDam = { si: "#000" };
Object.setPrototypeOf(motDam, mot);

mot.pik = 4;
alert(Object.getPrototypeOf(motDam)===mot);
alert(motDam.kha); // ได้ 6
alert(motDam.si); // ได้ #000
alert(motDam.pik); // ได้ 4
mot.kha = 5;
alert(motDam.kha); // ได้ 5

ตัวฟังก์ชันนี้เมื่อใช้แล้วก็มีการคืนตัวออบเจ็กต์กลับมา ดังนั้นสามารถใช้กับออบเจ็กต์เปล่าเพื่อสร้างออบเจ็กต์ตัวใหม่ที่มีโพรโทไทป์เป็นออบเจ็กต์ที่ต้องการได้ เช่น
let maeo = { kha: 4, hang: 1 };
let maeoDam = Object.setPrototypeOf({}, maeo);
alert(Object.getPrototypeOf(maeoDam) === maeo); // ได้ true
alert(maeoDam.kha); // ได้ 4




Object.getOwnPropertySymbols

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

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

แต่หากต้องการให้แสดงพรอเพอร์ตีที่มีคีย์เป็นซิมโบลทั้งหมดออกมาก็สามารถทำได้โดยใช้ Object.getOwnPropertySymbols()

ตัวอย่าง
const TAMAYA = Symbol();
const KAGIYA = Symbol();
let hanabi = {
  [TAMAYA]: "ทามายะ",
  [KAGIYA]: "คางิยะ"
};

alert(TAMAYA in hanabi); // ได้ true
alert(KAGIYA in hanabi); // ได้ true

let prosy = Object.getOwnPropertySymbols(hanabi);
alert(prosy.map(s => typeof s)); // ได้ symbol,symbol
alert(prosy.map(s => hanabi[s])); // ได้ ทามายะ,คางิยะ
alert(TAMAYA == prosy[0]); // ได้ true
alert(KAGIYA == prosy[1]); // ได้ true




Object.getOwnPropertyDescriptors [ES2017]

ใน ES5 มีฟังก์ชัน Object.getOwnPropertyDescriptor() สำหรับดูคำอธิบายคุณสมบัติของพรอเพอร์ตีซึ่งสามารถตั้งขึ้นมาจาก Object.definePropertie หรือ Object.defineProperties (รายละเอียด บทที่ ๒๖)

สำหรับใน ES2017 ได้เพิ่ม Object.getOwnPropertyDescriptors() เอาไว้แสดงคำอธิบายของพรอเพอร์ตีทั้งหมดที่มีอยู่ในออบเจ็กต์ออกมาทั้งหมด ซึ่งรวมถึงพรอเพอร์ตีที่ชื่อคีย์เป็นซิมโบลด้วย

ตัวอย่าง
const ATK = Symbol();
let puenyai = { nak: 2000 };
Object.defineProperties(puenyai, {
  yao: {
    value: 5,
    writable: false,
    enumerable: true
  },
  [ATK]: {
    value: 999,
    configurable: true
  }
});

let prodes = Object.getOwnPropertyDescriptors(puenyai);
alert(prodes[ATK].value); // ได้ 999
alert(prodes.yao.value); // ได้ 5
alert(prodes.nak.value); // ได้ 2000
alert(prodes.yao.writable); // ได้ false
alert(prodes[ATK].configurable); // ได้ true
alert(prodes.yao.enumerable); // ได้ true




Object.values และ Object.entries [ES2017]

ใน ES5 มีฟังก์ชัน Object.keys ไว้สำหรับไล่ดูชื่อคีย์ของพรอเพอร์ตีทั้งหมดออกมาเป็นแถวลำดับ ดังที่เขียนไปในบทที่ ๒๖

ใน ES2017 ได้เพิ่มฟังก์ชัน Object.values ไว้สำหรับดูค่า และ Object.entries สำหรับดูคีย์และค่าพร้อมกัน

วิธีการใช้คล้ายกับเมธอด .keys .values .entries ในแถวลำดับซึ่งได้เขียนถึงไปในบทที่ ๔๖ แต่เป็นฟังก์ชันที่ใช้กับออบเจ็กต์ใดๆก็ได้

ตัวอย่างการใช้
let hanayamata = {
  naru: 150,
  hana: 144,
  yaya: 158,
  tami: 155,
  machi: 163
};

alert(Object.keys(hanayamata)); // ได้ naru,hana,yaya,tami,machi
alert(Object.values(hanayamata)); // ได้ 150,144,158,155,163
let ent = Object.entries(hanayamata);
alert(ent.length); // ได้ 5
alert(ent[0]); // ได้ naru,150
alert(ent[1]); // ได้ hana,144
alert(ent[2]); // ได้ yaya,158
alert(ent[3]); // ได้ tami,155

ทั้ง Object.keys, Object.values และ Object.entries จะไม่แสดงพรอเพอร์ตีที่ไม่สามารถไล่เรียงได้ (enumerable เป็น false) รวมถึงที่คีย์เป็นซิมโบล




Object.fromEntries [ES2019]

Object.fromEntries เพิ่มเข้ามาใน ES2019 เป็นฟังก์ชันที่ทำงานตรงกันข้ามกับ Object.entries คือจะสร้างออบเจ็กต์ขึ้นมาจากแถวลำดับของคู่คีย์และค่าพรอเพอร์ตี

ตัวอย่างการใช้
let ent = [
  ["hinako", 160],
  ["mayuki", 139],
  ["kuina", 155],
  ["chiaki", 169],
  ["yua", 158],
];

let hinakonote = Object.fromEntries(ent);
alert(hinakonote.yua); // ได้ 158
alert(Object.keys(hinakonote)); // ได้ hinako,mayuki,kuina,chiaki,yua
alert(Object.values(hinakonote)); // ได้ 160,139,155,169,158




สรุปฟังก์ชันทั้งหมด

ชื่อฟังก์ชัน ความสามารถ เพิ่มมาใน
Object.assign แจกพรอเพอร์ตีจากออบเจ็กต์อื่นให้ออบเจ็กต์ตัวหนึ่ง ES2015
Object.is เทียบว่าออบเจ็กต์หรือตัวแปร ๒ ตัวมีค่าเท่ากันหรือเปล่า
Object.setPrototypeOf ตั้งโพรโทไทป์ให้ออบเจ็กต์
Object.getOwnPropertySymbols แสดงพรอเพอร์ตีที่ใช้คีย์เป็นซิมโบลทั้งหมด
Object.getOwnPropertyDescriptors แสดงพรอเพอร์ตีทั้งหมด ES2017
Object.values แสดงค่าทั้งหมดของพรอเพอร์ตีในออบเจ็กต์
Object.entries แสดงคีย์ทั้งหมดของพรอเพอร์ตีในออบเจ็กต์
Object.fromEntries แสดงคีย์และค่าทั้งหมดของพรอเพอร์ตีในออบเจ็กต์ ES2019







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

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

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

หมวดหมู่

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

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

ไทย

日本語

中文