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



javascript เบื้องต้น บทที่ ๑๙: การสร้างเมธอดให้ออบเจ็กต์
เขียนเมื่อ 2019/07/31 23:30
แก้ไขล่าสุด 2024/03/28 23:05


การสร้างเมธอด

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

ฟังก์ชันที่ถูกสร้างเป็นพรอเพอร์ตีในออบเจ็กต์มักจะถูกเรียกว่าเมธอด

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

ตัวอย่างการสร้างและใช้เมธอด
var maeo = {
  chue: "ทามะ",
  rongmiao: function() {
    alert("เหมียวๆ");
  }
};
maeo.rongmiao(); // ได้ เหมียวๆ

อาจสร้างฟังก์ชันไว้ข้างนอกแล้วค่อยป้อนให้
rongmiao = function() {
  alert("เหมียวๆ");
};
var maeo = { chue: "ทามะ", rongmiao: rongmiao };

หรือใส่เข้าไปทีหลังเหมือนป้อนค่าพรอเพอร์ตีธรรมดาก็ได้
var maeo = { chue: "ทามะ" };
maeo.rongmiao = function() {
  alert("เหมียวๆ");
};

ไม่ว่าจะแบบไหนกทำให้ออบเจ็กต์ meao มีเมธอด rongmiao ที่ใช้งานได้เหมือนกัน



ความแตกต่างระหว่างเมธอดกับฟังก์ชันธรรมดา

จากตัวอย่างการสร้างเมธอดจะเห็นว่าเมธอดก็คือฟังก์ชันธรรมดา แค่เอามาใส่ไว้ในออบเจ็กต์เท่านั้น

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

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

ตัวอย่างเช่น เมธอดต่างๆในออบเจ็กต์แถวลำดับ เช่น join
var lukchin = ["๐", "o", "ㅇ"];
var kebab = ["口", "ロ", "ㅁ"];
alert(lukchin.join("-")); // ได้ ๐-o-ㅇ
alert(kebab.join("-")); // ได้ 口-ロ-ㅁ

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

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

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

วิธีการที่เมธอดจะใช้ค่าต่างๆภายในออบเจ็กต์ได้นั้น จะทำโดยผ่านตัวแปรพิเศษที่ชื่อ this



การใช้ this ในเมธอด

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

คำว่า this เป็นภาษาอังกฤษที่มีความหมายว่า "นี่" ดังนั้นมันจึงเป็นตัวแปรที่ใช้แทน "ตัวเอง" นั่นเอง

ตัวเองในที่นี้หมายถึงออบเจ็กต์ที่เรียกมัน หาก this ถูกเรียกใช้ในเมธอดของออบเจ็กต์ งั้น this ก็คือตัวแปรที่แทนออบเจ็กต์นั้น

ตัวอย่าง
var thakthai = function() {
  alert("สวัสดี ฉันชื่อ" + this.chue);
};
var akari = {
  chue: "อาการิ",
  thakthai: thakthai
};
var hikari = {
  chue: "ฮิการิ",
  thakthai: thakthai
};

akari.thakthai(); // ได้ สวัสดี ฉันชื่ออาการิ
hikari.thakthai(); // ได้ สวัสดี ฉันชื่อฮิการิ

จะเห็นว่าเมธอด thakthai ไปดึงเอาพรอเพอร์ตี chue มาใช้ โดยผ่าน this.chue ดังนั้นต่อให้ออบเจ็กต์ทั้ง ๒ นี้มีเมธอดแบบเดียวกันอยู่ แต่ก็จะแสดงผลไม่เหมือนกัน



this เมื่ออยู่นอกออบเจ็กต์

ดังที่ได้อธิบายไปแล้วว่า this จะแทนออบเจ็กต์ที่เป็นตัวเรียกใช้ แต่ว่าถ้าหากเรียกใช้ this จากด้านนอกออบเจ็กต์ แบบนี้ this ควรจะแทนอะไร?

คำตอบก็คือ this จะแทนออบเจ็กต์ global

global เป็นออบเจ็กต์ที่ห่อหุ้มตัวโปรแกรมทั้งหมด

ปกติแล้วเวลาที่เราประกาศตัวแปรขึ้นมานั้น จริงๆแล้วถือเป็นการสร้างพรอเพอร์ตีให้กับ global นั่นหมายความว่าค่าทั้งหมดที่เรียกผ่านตัวแปรนั้นสามารถเรียกโดยผ่านพรอเพอร์ตีของ this ได้เช่นกัน
var x = 1.1;
alert(this.x); // ได้ 1.1
alert(this.x === x); // ได้ true

เพียงแต่ว่าการเข้าถึงตัวแปรโดยผ่าน this นั้น หากตัวแปรนั้นไม่ได้ถูกนิยามไว้ก็จะแค่ได้ undefined แต่ถ้าเข้าผ่านตัวแปรโดยตรง จะเกิดข้อผิดพลาด
alert(this.y); // ได้ undefined
alert(y); // ได้ ReferenceError: y is not defined

กรณีที่รันผ่านเบราว์เซอร์ ออบเจ็กต์ global ก็คือออบเจ็กต์ window แบบนี้ this กับ window ก็คือสิ่งเดียวกัน อาจเข้าผ่านตัวแปร window ได้
alert(this); // ได้ [object Window]
alert(this === window); // ได้ true

นั่นเพราะ สำหรับเบราว์เซอร์แล้ว สถานที่ที่รันโปรแกรมก็คือตัวหน้าต่างเบราว์เซอร์นั่นเอง

ให้ระวังว่า this จะแทนตัวออบเจ็กต์เมื่อถูกเรียกผ่านเมธอดเท่านั้น แต่หากใช้ this ในโครงสร้างตอนที่สร้างออบเจ็กต์ แบบนั้น this ก็ไม่ได้หมายถึงตัวออบเจ็กต์​แต่หมายถึงตัว global

ตัวอย่าง
var a = 2;
var obj = {
  a: 1,
  f: this.a
};
alert(obj.f); // ได้ 2

แบบนี้ this.a จะแทนค่าตัวแปร a คือ 2 ไม่ได้มาแทน obj.a



การเรียกใช้เมธอดด้วย call หรือ apply

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

แต่นอกจากนี้เมธอดอาจถูกเรียกได้โดยผ่านเมธอดที่ชื่อ call

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

เช่นสร้างฟังก์ชันขึ้นมา ให้มีการเรียกตัวแปร this ถ้าเติม ( ) เรียกเฉยๆ this ก็จะหมายถึงตัว global แต่หากใช้ .call() แล้วใส่ค่าลงไป this ก็จะแทนค่านั้น
var f = function() {
  alert(this);
};

f(); // ได้ [object Window]

var a = "นี่";
f.call(a); // ได้ นี่

หากฟังก์ชันนั้นมีพารามิเตอร์ ต้องใส่ค่าต่อจากตัวที่จะให้แทน this
var f = function(x, y) {
  alert(this + x + y);
};

f("*", "+"); // ได้ [object Window]*+

var a = "#";
f.call(a, "*", "+"); // ได้ #*+

นอกจากนี้ยังมีเมธอด apply ซึ่งจะคล้ายกับ call แต่จะรับอาร์กิวเมนต์ที่เหลือนอกจาก this ในรูปของแถวลำดับ

หากใช้ apply แทน call ในตัวอย่างที่แล้วก็จะเขียนแบบนี้
var a = "1";
f.apply(a, ["2", "3"]); // ได้ 123

กรณีที่ call หรือ apply ถูกเรียกในฐานะเมธอดในออบเจ็กต์ก็เช่นเดียวกัน เมื่อใช้ call หรือ apply นั้น this จะแทนอาร์กิวเมนต์ตัวแรกที่ป้อนเข้าไปเสมอ โดยไม่สนว่าถูกเรียกจากออบเจ็กต์ไหน

ตัวอย่างเช่น มีผู้กล้ากับนักเวทอยู่ นักเวทมีเมธอด (สกิล) ฟื้น HP
var phukla = {
  chue: "นิเกะ",
  HP: 20
};
var nakwet = {
  chue: "คุคุริ",
  HP: 12,
  fuenHP: function(x) {
    this.HP += x;
    alert(this.chue + "ได้ฟื้น HP " + x);
  }
};

nakwet.fuenHP(10); // ได้ คุคุริได้ฟื้น HP 10
alert(nakwet.HP); // ได้ 22
nakwet.fuenHP.call(phukla, 8); // ได้ นิเกะได้ฟื้น HP 8
alert(phukla.HP); // ได้ 28
(นิเกะ & คุคุริ ที่มา)

เมื่อเรียกเมธอด fuenHP ที่ตัวนักเวทโดยตรงจะได้ว่า HP ของนักเวทเพิ่ม แต่ถ้าใช้ .call แล้วใส่ออบเจ็กต์ phukla ไป แบบนี้จึงจะเป็นการฟื้น HP ให้ผู้กล้า

จะเห็นว่าตัวแปร this นี้ค่อนข้างพิเศษ จึงต้องระวังเวลาใช้ ต้องรู้ว่าเวลาไหนจะแทนอะไร



เขียนทับเมธอดที่มีอยู่แล้ว

ออบเจ็กต์นั้นแรกเริ่มเมื่อสร้างก็มีเมธอดที่เป็นพื้นฐานติดตัวอยู่แล้ว ดังเช่นเมธอด toString ดังที่กล่าวถึงไปในบทที่ ๕

แต่ว่าเมธอดพวกนี้เป็นสิ่งที่สามารถเขียนทับได้ หากต้องการ

ปกติหากใช้ .toString กับข้อมูลชนิดออบเจ็กต์จะได้ผลเป็น [object Object] โดยไม่แสดงเนื้อหาข้างในว่ามีอะไรเลย

เวลาที่ใช้ alert โดยตรงกับออบเจ็กต์จึงไม่ได้ข้อมูลอะไรเกี่ยวกับออบเจ็กต์นั้นเลย

เพื่อให้ออบเจ็กต์สามารถแสดงรายละเอียด เราสามารถกำหนดเมธอด toString ใหม่ได้ โดยเขียนทับลงไป

ตัวอย่าง
var miniryū = {
  chue: "มินิริว",
  chanit: "มังกร",
  sung: 1.8,
  namnak: 3.3,
  toString: function() {
    return (
      this.chue +
      "\nชนิด: " +
      this.chanit +
      "\nสูง / หนัก: " +
      this.sung +
      " เมตร / " +
      this.namnak +
      " กิโลกรัม"
    );
  }
};
alert(miniryū);
ได้
มินิริว
ชนิด: มังกร
สูง / หนัก: 1.8 เมตร / 3.3 กิโลกรัม

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




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

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

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

หมวดหมู่

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

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

目录

从日本来的名言
模块
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
机器学习
-- 神经网络
javascript
蒙古语
语言学
maya
概率论
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
-- 与香港相关的日记
-- 与澳门相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



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

  查看日志

  推荐日志

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