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



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


ความหมายของฟังก์ชัน

คำว่าฟังก์ชัน (function) นั้นเป็นคำที่มีความหมายหลากหลาย ซึ่งแล้วแต่ว่าพูดถึงเรื่องอะไรอยู่

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

เช่น
f(x) = (x+8)/2

แบบนี้เมื่อใส่ค่า x เป็น 2 ก็จะได้ค่า f(x) เป็น 5 กลับมา

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

ยกตัวอย่างเช่น ฟังก์ชัน parseInt ในจาวาสคริปต์
var s = "005.00";
var x = parseInt(s); // x จะกลายเป็น 5

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

แบบนี้เรียกว่าการคืนค่า (return) ของฟังก์ชัน

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

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

เช่น
var al = alert("555+");

แบบนี้จะมีข้อความ 555+ เด้งออกมา แต่ค่าของตัวแปร al จะกลายเป็น undefined

โดยรายละเอียดแล้ว ฟังก์ชันในโปรแกรมแต่ละภาษาจะต่างกันออกไป

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

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

เช่นใน alert("555+") นี้ "555+" คืออาร์กิวเมนต์ของฟังก์ชัน alert นี้

ฟังก์ชันไหนจะต้องการอาร์กิวเมนต์อะไรบ้างนั้นถูกกำหนดไว้ตั้งแต่ตอนสร้างฟังก์ชันแล้ว

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



การสร้างฟังก์ชันไร้ชื่อด้วยคำสั่ง function

วิธีการสร้างฟังก์ชันที่ง่ายและพบบ่อยที่สุดคือการใช้คำสั่ง function ในการสร้าง

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

โครงสร้างเป็นดังนี้
var ชื่อตัวแปร = function(พารามิเตอร์){
  เนื้อหาในฟังก์ชัน
}

"พารามิเตอร์" (parameter)
ก็คือค่าที่ต้องการรับเข้ามาใช้ในฟังก์ชัน

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

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

ตัวอย่างการสร้าง ลองสร้างฟังก์ชันง่ายๆที่แค่มีการใช้ alert เพื่อแสดงค่า (x+8)/2
var f = function(x) {
  alert((x + 8) / 2);
};

จากนั้นก็เรียกใช้งานโดยใส่ชื่อฟังก์ชันแล้วตามด้วยวงเล็บ ในวงเล็บป้อนค่าลงไป
f(2); // ได้ 5
f(3); // ได้ 5.5

ในที่นี้เมื่อ 2 เป็นอาร์กิวเมนต์ จะถูกแทนค่าลงในพารามิเตอร์ x แล้วจะขึ้น alert เลข 5 ออกมา ถ้าใส่ 3 ไปก็จะกลายเป็น 5.5

ตัวอย่างข้างต้นนี้เป็นกรณีของฟังก์ชันที่ไม่มีการคืนค่า แต่สำหรับฟังก์ชันที่มีการคืนค่าจะต้องมีคำสั่ง return
var f = function(x) {
  return (x + 8) / 2;
};

var a = f(2);
alert(a); // ได้ 5



ฟังก์ชันที่มีพารามิเตอร์หลายตัว

พารามิเตอร์อาจมีกี่ตัวก็ได้ เวลาเรียกใช้ก็ต้องใส่อาร์กิวเมนต์ตามจำนวนนั้น ค่าที่ใส่จะถูกแทนลงในพารามิเตอร์ตามลำดับ
var f = function(x, y, z) {
  return "x=" + x + " y=" + y + " z=" + z;
};

alert(f(2, 3, 4)); // ได้ x=2 y=3 z=4

ถ้าจำนวนของอาร์กิวเมนต์น้อยกว่าพารามิเตอร์ ตัวที่เกินมาจะเป็น undefined
alert(f(2, 3)); // ได้ x=2 y=3 z=undefined

ถ้าใส่เกินมา ตัวที่เกินจะถูกมองข้ามไป ไม่ได้ใช้ ผลก็จะไม่ต่างจากใส่พอดีจำนวน
alert(f(2, 3, 4, 5)); // ได้ x=2 y=3 z=4

แต่ก็ไม่ใช่ว่าการใส่พารามิเตอร์เกินมาจะไม่มีผลใดๆเลย ที่จริงในฟังก์ชันจะมีตัวแปรติดตัวที่เรียกว่า arguments อยู่ ซึ่งจะเก็บอาร์กิวเมนต์ทั้งหมดที่ถูกใส่เข้ามา เช่น
var f = function(x) {
  return "x=" + x + " arguments=" + arguments;
};

alert(f(3, 5)); // ได้ x=3 arguments=[object Arguments]

arguments นี้เป็นออบเจ็กต์ตัวหนึ่ง ซึ่งเก็บอาร์กิวเมนต์แต่ละตัวที่ใส่เข้าไปไว้
var f = function(x) {
  var s = "x=" + x;
  s += " arg0=" + arguments[0];
  s += " arg1=" + arguments[1];
  s += " arg2=" + arguments[2];
  return s;
};

alert(f(3, 5)); // ได้ x=3 arg0=3 arg1=5 arg2=undefined

ด้วยการใช้ arguments จะทำให้สามารถสร้างฟังก์ชันที่ไม่จำกัดตัวแปรได้

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



เกี่ยวกับคำสั่ง return

คำสั่ง return มีรายละเอียดปลีกย่อยในการใช้ที่จำเป็นต้องมาเน้นกันสักหน่อย

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

เช่น
var f = function() {
  s = "เธอเก่ง";
  return s;
  s += "น้อยกว่าเขา";
  alert(s);
};

alert(f()); // ได้ เธอเก่ง

แบบนี้คำสั่งในฟังก์ชันหลัง return s จะไม่ทำงาน

ต่อมา คำสั่ง return สามารถใส่หลายอันก็ได้ แต่เฉพาะอันที่เจอก่อนเท่านั้นจึงจะถูกใช้

ที่มักเจอบ่อยก็คือเมื่อใช้ if เช่น
var f = function(x, y) {
  if (x > y) return "x มากกว่า y";
  else if (x == y) return "x เท่ากับ y";
  else return "x น้อยกว่า y";
};

alert(f(4, 6)); // ได้ x น้อยกว่า y
alert(f(19, 7)); // ได้ x มากกว่า y

ที่จริงแล้วในตัวอย่างนี้ else อาจละได้ เพราะ ถ้าเข้าเงื่อนไขตั้งแต่แรกก็เจอ return ตัวแรก ยังไงคำสั่งที่อยู่ใน else ก็ไม่ถูกใช้

ดังนั้นในฟังก์ชันเขียนแบบนี้ก็ได้ผลเหมือนเดิม
var f = function(x, y) {
  if (x > y) return "x มากกว่า y";
  if (x == y) return "x เท่ากับ y";
  return "x น้อยกว่า y";
};

return ไม่จำเป็นต้องมีค่าตามหลัง อาจใส่ return เฉยๆ กรณีนี้จะหมายความว่าให้สิ้นสุดการทำงานของฟังก์ชันโดยไม่ส่งคืนค่าใดๆออกมา ค่าคืนกลับของฟังก์ชันนั้นจะกลายเป็น undefined
var f = function(x) {
  return;
};
var a = f(29);

alert(a); // ได้ undefined



ค่าคืนกลับต้องเขียนอยู่บรรทัดเดียวกันกับ return

ข้อควรระวังอีกอย่างคือหลัง return ต้องตามด้วยค่าที่ต้องการให้คืนกลับทันทีโดยห้ามขึ้นบรรทัดใหม่ เพราะถ้าขึ้นบรรทัดใหม่จะถูกตีความเป็นคนละคำสั่งกัน จะกลายเป็นว่าให้ return โดยไม่มีการคืนค่า
var f = function(x) {
  return
  x / 2 - (x * x) / 10 + 5;
};

var a = f(29);
alert(a); // ได้ undefined

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

แต่ก็สามารถใช้วงเล็บช่วยได้ หากต้องการขึ้นบรรทัดใหม่จริงๆ เช่น
var f = function (x) {
  return (
    (x / 2) - x * x / 10 + 5
  );
};
var a = f(20);
alert(a); // ได้ -25



การสร้างฟังก์ชันมีชื่อ ด้วยคำสั่ง function

การสร้างฟังก์ชันที่อธิบายมาตั้งแต่ต้นบทนั้นเป็นการสร้างฟังก์ชันแบบไร้ชื่อ

อีกวิธีในการสร้างฟังก์ชันคือสร้างโดยใช้คำสั่ง function นำหน้าชื่อตัวแปรฟังก์ชัน คือเขียนแบบนี้
function ชื่อตัวแปร(พารามิเตอร์){
  เนื้อหาในฟังก์ชัน
}

ตัวอย่าง
function f(x) {
  return "2x = " + x * 2;
}
alert(f(1.1)); // ได้ 2x = 2.2

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

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

จะเห็นได้จากตอนที่สั่งดูค่า เช่นโดยใช้ alert จะมีชื่อของฟังก์ชันขึ้น ตรงกับชื่อตัวแปรที่ใช้แทนฟังก์ชัน
function wangplao() {}
alert(wangplao); // ได้ function wangplao() {}

แต่หากลองใช้วิธีสร้างแบบไร้ชื่อ ฟังก์ชันที่ได้จะไม่มีชื่อฟังก์ชันปรากฏขึ้นมาด้วย
wangplao = function() {};
alert(wangplao); // ได้ function() {}

ดังนั้นในกรณีฟังก์ชันไร้ชื่อ ตัวแปรเป็นแค่ตัวเก็บฟังก์ชัน ชื่อตัวแปรไม่ได้เป็นชื่อฟังก์ชันไปด้วย ตัวฟังก์ชันจริงๆนั้นไร้ชื่อ

นอกจากนี้ข้อแตกต่างอีกอย่างคือเรื่องลำดับในการทำงานของโปรแกรม ขอยกตัวอย่างดังนี้

กรณีฟังก์ชันไร้ชื่อ
alert(f); // ได้ undefined
f = 1;
alert(f); // ได้ 1
var f = function(x) {return "2x = " + x * 2;}
alert(f); // ได้ function f(x) {return "2x = " + x * 2;}
f = 1;
alert(f); // ได้ 1

กรณีฟังก์ชันมีชื่อ
alert(f); // ได้ function f(x) {return "2x = " + x * 2;}
f = 1;
alert(f); // ได้ 1
function f(x) {return "2x = " + x * 2;}
alert(f); // ได้ 1
f = 1;
alert(f); // ได้ 1

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

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

ส่วนการนิยามฟังก์ชันแบบมีชื่อ (ใช้ function ขึ้นต้น) นั้น ไม่ว่าจะวางไว้ส่วนไหนในโปรแกรม ก็จะถูกอ่านก่อนเสมอ ดังนั้นแม้แต่ส่วนที่วางไว้ก่อนบรรทัดที่นิยามฟังก์ชัน ก็จะเห็นว่าตัวแปรที่ประกาศเป็นฟังก์ชันนั้นมีสถานะเป็นฟังก์ชันอยู่

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

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



การสร้างฟังก์ชันด้วย new Function

อีกวิธีที่ใช้สร้างฟังก์ชันขึ้นมาคือใช้คอนสตรักเตอร์ คือเขียน new Function (คราวนี้ต้องขึ้นต้นด้วยตัว F ตัวพิมพ์ใหญ่)

โครงสร้างเป็นดังนี้
var ชื่อตัวแปร = new Function(พารามิเตอร์, ..., เนื้อหาฟังก์ชัน)

ตัวอย่าง
var haPhuenthiSamliam = new Function("than", "sung", "return than*sung/2;");
alert(haPhuenthiSamliam); // ได้ function anonymous(than,sung) {return than * sung / 2;}
alert(haPhuenthiSamliam(4, 5)); // ได้ 10

เทียบเท่ากับการเขียนฟังก์ชันไร้ชื่อด้วย function แบบนี้
var haPhuenthiSamliam = function(than, sung) {return (than * sung) / 2;};
alert(haPhuenthiSamliam); // ได้ function(than, sung) {return (than * sung) / 2;}

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

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



ขอบเขตการใช้งานของตัวแปร

ปกติแล้วหากมีการประกาศตัวแปรขึ้นภายในโครงสร้างการนิยามฟังก์ชัน ตัวแปรนั้นจะมีผลแค่ภายในฟังก์ชันนั้น ดังนั้นหากเรียกตัวแปรนั้นนอกฟังก์ชันก็จะพบว่าไม่มีค่า แม้ว่าจะมีการเรียกใช้ฟังก์ชันนั้นแล้วก็ตาม เช่น
var f = function(x) {
  var k = 5;
  alert(k + x);
};

f(6); // ได้ 11
alert(k); // ได้ ReferenceError: k is not defined

เพราะว่ากรณีนี้ k จะถือว่าเป็นตัวแปรเฉพาะที่ (local variable) คือใช้ได้เฉพาะที่ในกรอบวงเล็บปีกกา { } ที่เป็นโครงสร้างฟังก์ชัน

อย่างไรก็ตาม หากประกาศตัวแปรโดยไม่ใช้ var ตัวแปรนั้นจะเป็นตัวแปรครอบคลุม (global variable) นั่นคือตัวแปรที่สามารถเรียกใช้จากที่ไหนก็ได้ในโปรแกรม
var f = function(x) {
  k = 5;
  alert(k + x);
};

f(6); // ได้ 11
alert(k); // ได้ 5

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

จากข้อแตกต่างตรงนี้ ทำให้เวลาประกาศตัวแปรมักจะต้องใส่ var ไว้ เพื่อให้รู้ว่าเป็นตัวแปรที่มีผลเฉพาะในขอบเขตนั้น

แต่ตัวแปรที่ประกาศข้างนอก จะใส่ var หรือไม่ก็ถือเป็นตัวแปรครอบคลุมที่ใช้ได้ทุกที่เหมือนกัน เช่น
var a = 10;
var f = function() {
  alert(a);
};

f(); // ได้ 10

แบบนี้ตราบใดที่ไม่มีการประกาศตัวแปร a ภายในฟังก์ชัน f ตัวแปร a ภายในฟังก์ชัน f ก็จะยังถูกตีความว่าเป็นตัวแปร a จากด้านนอกอยู่

ที่ไม่นิยมใช้ตัวแปรครอบคลุมก็เพราะกรณีที่ตัวแปรในฟังก์ชันเผลอไปซ้ำกับตัวแปรนอกฟังก์ชันจะทำให้เกิดปัญหาที่ไม่คาดคิดได้

ลองดูตัวอย่างต่อไป
var a = 7;
var f = function() {
  var a = 2;
  alert(a);
};

f(); // ได้ 2
alert(a); // ได้ 5

กรณีนี้ตัวแปร a มีการประกาศไว้ข้างนอก และในฟังก์ชันก็มีการประกาศด้วย แบบนี้ตัวแปร a ข้างในและนอกถือเป็นคนละตัว

แต่ถ้าหากไม่ใส่ var ด้านใน จะทำให้ตัวแปร a ถูกตีความว่าเป็นตัวเดียวกับ a ข้างนอก ค่าจึงถูกเขียนทับไป
var a = 7;
var f = function() {
  a = 2;
  alert(a);
};

f(); // ได้ 2
alert(a); // ได้ 2

แต่ความซับซ้อนของเรื่องนี้ไม่ได้มีอยู่แค่นั้น

เมื่อมีการใช้ var ประกาศตัวแปรเฉพาะที่ในฟังก์ชัน กรณีที่มีการเรียกใช้ตัวแปรเฉพาะที่ก่อนที่จะมีการประกาศ จะพบว่าค่านั้นเป็น undefined
var ahan = "ข้าวเกรียบ";
var f = function() {
  alert(ahan); // ได้ undefined
  var ahan = "ข้าวตัง";
  alert(ahan); // ได้ ข้าวตัง
};

f();
alert(ahan); // ได้ ข้าวเกรียบ

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



ความเปลี่ยนแปลงที่เกิดกับค่าที่ใช้เป็นอาร์กิวเมนต์ในฟังก์ชัน

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

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

เช่น
var f = function(x) {
  x = x+1;
  alert(x); // ได้ 1
};

var a = 0;
f(a);
alert(a); // ได้ 0

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

แต่ว่าผลจะต่างออกไป หากอาร์กิวเมนต์นั้นเป็นออบเจ็กต์ และการเปลี่ยนแปลงนั้นเกิดขึ้นที่พรอเพอร์ตีของออบเจ็กต์ เช่น
var hai5baht = function(k) {
  alert("มีเหรียญ 5 อยู่ " + k.rian5 + " เหรียญ"); // ได้ มีเหรียญ 5 อยู่ 1 เหรียญ
  k.rian5 = k.rian5 + 1;
  alert("มีเหรียญ 5 อยู่ " + k.rian5 + " เหรียญ"); // ได้ มีเหรียญ 5 อยู่ 2 เหรียญ
};

var krapaotang = { rian5: 1, rian10: 6 };
hai5baht(krapaotang);
alert("มีเหรียญ 5 อยู่ " + krapaotang.rian5 + " เหรียญ"); // ได้ มีเหรียญ 5 อยู่ 2 เหรียญ

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

อย่างไรก็ตาม หากเปลี่ยนเป็นเขียนแบบนี้จะเท่ากับเป็นการสร้างออบเจ็กต์ใหม่ทับตัวแปร k เดิม แบบนี้จะไม่มีผลต่อ krapaotang
var hai5baht = function(k) {
  alert("มีเหรียญ 5 อยู่ " + k.rian5 + " เหรียญ"); // ได้ มีเหรียญ 5 อยู่ 1 เหรียญ
  k = { rian5: k.rian5 + 1 };
  alert("มีเหรียญ 5 อยู่ " + k.rian5 + " เหรียญ"); // ได้ มีเหรียญ 5 อยู่ 2 เหรียญ
};

var krapaotang = { rian5: 1, rian10: 6 };
hai5baht(krapaotang);
alert("มีเหรียญ 5 อยู่ " + krapaotang.rian5 + " เหรียญ"); // ได้ มีเหรียญ 5 อยู่ 1 เหรียญ

ตรงนี้เป็นส่วนที่ต้องค่อยๆทำความเข้าใจให้ดีเพื่อจะได้ไม่เกิดข้อผิดพลาดที่ไม่คาดคิด




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

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

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

หมวดหมู่

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

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

ไทย

日本語

中文