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



javascript เบื้องต้น บทที่ ๒๙: การใช้โหมดเคร่งครัด และอื่นๆ
เขียนเมื่อ 2019/08/13 00:36
แก้ไขล่าสุด 2021/09/28 16:42


บทนี้จะแนะนำความสามารถใน ES5 ที่เหลือที่ไม่ได้กล่าวถึงในบทก่อนๆ



โหมดเคร่งครัด

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

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

โหมดนี้จะทำให้เมื่อเขียนโค้ดในแบบที่ไม่ควรเขียนก็จะเกิดข้อผิดพลาด (error) ขึ้น แล้วโปรแกรมก็จะหยุดไป

การเปิดโหมดนี้อาจทำได้ทั้งเปิดให้มีผลทั้งโปรแกรม กับเปิดใช้เฉพาะในฟังก์ชันก็ได้

เมื่อเปิดแล้ว การกระทำต่อไปนี้จะทำให้เกิดข้อผิดพลาด
  • ประกาศตัวแปรโดยไม่ใช้ var
  • ใช้ชื่อพารามิเตอร์ในฟังก์ชันซ้ำ
  • ป้อนค่าทับตัวแปร arguments ในฟังก์ชัน
  • เข้าถึง arguments.callee
  • ป้อนค่าเข้า undefined
  • ใช้ with
  • ละเมิดข้อจำกัดการเปลี่ยนแปลงของตัวออบเจ็กต์ (บทที่ ๒๕)
  • ละเมิดข้อจำกัดการเปลี่ยนแปลงของพรอเพอร์ตี (บทที่ ๒๖)
นอกจากนี้ การกระทำเหล่านี้จะทำให้ผลลัพธ์เปลี่ยนไปจากเดิม
  • ตัวแปรที่ประกาศใน eval จะใช้นอก eval ไม่ได้
  • this เมื่อใช้ในฟังก์ชันนอกออบเจ็กต์จะไม่แทนตัว global แต่จะกลายเป็น undefined
หลายอย่างที่กล่าวถึงในนี้จริงๆไม่เคยพูดถึงในบทที่ผ่านๆมาเลยด้วยซ้ำ เช่น with เพราะจริงๆแล้วเป็นสิ่งที่ไม่ได้ควรจะใช้อยู่แล้ว เลยไม่ได้จำเป็นจะต้องยกมาพูดถึงมากนัก

วิธีการเปิดโหมดเคร่งครัดทั้งตัวโปรแกรมนั้นทำได้โดยใส่ "use strict" ตอนเริ่มโปรแกรม

ตัวอย่าง

ประกาศตัวแปรโดยไม่ใช้ var
"use strict";
a = 1; // ได้ ReferenceError: assignment to undeclared variable a

ชื่อพารามิเตอร์ในฟังก์ชันซ้ำ
"use strict";
var f = function(x,x){} // ได้ SyntaxError: duplicate formal argument x

ป้อนค่าให้ตัวแปร arguments ในฟังก์ชัน
"use strict";
var f = function(){
  arguments = 1 // ได้ SyntaxError: 'arguments' can't be defined or assigned to in strict mode code
}

การป้อนค่าให้ undefined นั้นแต่ไหนแต่ไรเป็นสิ่งที่ถึงทำไปก็ไม่ได้มีผลอะไร เพราะ undefined เป็นค่าที่เขียนทับไม่ได้ แต่ก็ไม่เกิดข้อผิดพลาดขึ้น แต่พอเปิดโหมดนี้แล้วพอทำจะเกิดข้อผิดพลาด
"use strict";
undefined = 1; // ได้ TypeError: "undefined" is read-only

ออบเจ็กต์ที่ freeze ไว้ ปกติถ้าพยายามไปแก้ไขค่าจะแค่ไม่เกิดอะไรขึ้น แต่ถ้าเปิดโหมดนี้จะทำให้เกิดข้อผิดพลาดขึ้นทันที
"use strict";
var obj = { a: 1 };
Object.freeze(obj);
obj.a = 2; // ได้ TypeError: "a" is read-only
delete obj.a; // ได้ TypeError: property "a" is non-configurable and can't be deleted
obj.b = 3; // ได้ TypeError: can't define property "b": Object is not extensible

ข้อจำกัดในตัวพรอเพอร์ตี ซึ่งได้จากการใช้ Object.create หรือ Object.defineProperty ก็เช่นกัน
"use strict";
var obj = Object.create(
  {},
  {
    a: { value: 1, writable: false }
  }
);
obj.a = 3; // ได้ TypeError: "a" is read-only

เมื่อใช้ eval ตัวแปรที่ประกาศใน eval จะใช้ข้างนอก eval ไม่ได้
"use strict";
eval("var a = 1");
alert(a); // ได้ ReferenceError: a is not defined

เมื่อใช้ this ในฟังก์ชันที่ไม่ใช่อยู่ในออบเจ็กต์จะได้ไม่ชี้ถึงตัว global แต่ละได้ undefined
"use strict";
var f = function() {
  alert(this);
};
f(); // ได้ undefined



โหมดเคร่งครัดภายในฟังก์ชัน

ปกติถ้าใส่ "use strict" ตอนต้นโปรแกรมจะเป็นการเปิดให้มีผลทั้งโปรแกรม แต่หากต้องการให้เปิดโหมดแค่ในฟังก์ชันให้ใส่ "use strict" ตอนเริ่มฟังก์ชัน
var f = function() {
  "use strict";
  undefined = 1;
};
undefined = 1; // ไม่เกิดข้อผิดพลาด
f(); // TypeError: "undefined" is read-only



เมธอด trim

เมธอด trim ในข้อมูลชนิดสายอักขระจะสามารถทำการตัดช่องว่างหรือเว้นบรรทัดที่อยู่หน้าหรือหลังสุดทั้งหมดได้
var s = "   ทริม  ";
alert('"' + s + '"'); // ได้ "   ทริม  "
alert('"' + s.trim() + '"'); // ได้ "ทริม"



เมธอด indexOf และ lastIndexOf ในแถวลำดับ

เดิมทีเมธอด indexOf และ lastIndexOf เป็นเมธอดที่มีอยู่ในข้อมูลชนิดสายอักขระ ได้กล่าวถึงไปแล้วในบทที่ ๑๓

แต่ใน ES5 เมธอดนี้สามารถใช้ในแถวลำดับได้ด้วย

indexOf จะทำการค้นหาข้อมูลในแถวลำดับว่ามีตัวที่เราต้องการอยู่ในตำแหน่งไหน แล้วจะคืนค่าตำแหน่งนั้นมา โดยไล่หาจากซ้ายสุด (ตำแหน่ง 0) ถ้าเจออันไหนที่ตรงก็คืนเลขค่าลำดับตำแหน่งนั้น

ส่วน lastIndexOf จะเหมือนกัน แค่เริ่มไล่หาจากขางขวาสุดก่อน

หากค้นหาแล้วไม่เจอเลยจะได้ -1
var pk = ["ฮาเน็กโกะ", "โปโปกโกะ", "วาตักโกะ", "โปโปกโกะ", "ฮาเน็กโกะ"];
alert(pk.indexOf("ฮาเน็กโกะ")); // ได้ 0
alert(pk.indexOf("โปโปกโกะ")); // ได้ 1
alert(pk.lastIndexOf("โปโปกโกะ")); // ได้ 3
alert(pk.indexOf("โมโกโกะ")); // ได้ -1

สามารถกำหนดจุดเริ่มต้นการค้นได้โดยใส่อาร์กิวเมนต์ตัวที่ ๒ ลงไป ตัวที่อยู่ตำแหน่งก่อนหน้าเลขนั้นจะไม่ถูกค้นด้วย เลขตำแหน่งจะใช้เลขติดลบเพื่อคิดลำดับไล่จากท้ายมาก็ได้
alert(pk.indexOf("ฮาเน็กโกะ", 3)); // ได้ 4
alert(pk.indexOf("โปโปกโกะ", 2)); // ได้ 3
alert(pk.indexOf("วาตักโกะ", 3)); // ได้ -1
alert(pk.indexOf("วาตักโกะ", 2)); // ได้ 2
alert(pk.indexOf("โปโปกโกะ", -1)); // ได้ -1
alert(pk.indexOf("โปโปกโกะ", -2)); // ได้ 3



ฟังก์ชัน Array.isArray

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

ผลที่ได้จะคล้ายกับการใช้ instanceof array แต่มีความแตกต่างกันเล็กน้อยในบางสถานการณ์ แต่เป็นรายละเอียดปลีกย่อยซึ่งจะยังไม่เขียนถึงตรงนี้

ตัวอย่าง
alert(Array.isArray([])); // ได้ true
alert(Array.isArray(new Array("ก", "ข", "ค", "ง"))); // ได้ true
alert(Array.isArray(Array.prototype)); // ได้ true
alert(Array.isArray("Array")); // ได้ false
alert(Array.isArray()); // ได้ false
alert(Array.isArray({})); // ได้ false
alert(Array.isArray(null)); // ได้ false
alert(Array.isArray(99)); // ได้ false
alert(Array.isArray(true)); // ได้ false


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




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

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

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

หมวดหมู่

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

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

ไทย

日本語

中文