φυβλαςのβλογ
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
蒙古语
语言学
maya
概率论
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
-- 与香港相关的日记
-- 与澳门相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



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

  查看日志

  推荐日志

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