φυβλαςのβλογ
phyblas的博客



javascript เบื้องต้น บทที่ ๔๘: ฟังก์ชันเพิ่มเติมสำหรับออบเจ็กต์
เขียนเมื่อ 2020/05/15 00:58

ใน 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
-- opencv
-- pytorch
机器学习
-- 神经网络
maya
javascript
概率论
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
-- 与香港相关的日记
-- 与澳门相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



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

  查看日志

  推荐日志

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