ฉันต้องการเขียนไลบรารีคลาส JavaScript ที่มีประสิทธิภาพ แต่ฉันไม่สามารถเริ่มต้นได้
ลองอ่านห้องสมุดของคนอื่น แต่เข้าใจราวกับว่ามันเป็นที่เข้าใจ
ฉันวางแผนที่จะศึกษาฟังก์ชั่น JS ขั้นสูงได้ดี แต่เนื้อหาในหนังสือที่มีสิทธิ์กระจัดกระจายเกินไป
แม้ว่าคุณจะจำ "การใช้งาน" ได้ แต่คุณไม่ได้คิดถึง "วิธี" เมื่อคุณต้องการ "ใช้"
บางทีคุณอาจเป็นเช่นฉันดูเหมือนจะมีพลังที่มองไม่เห็นที่ยับยั้งแผนของเราทำให้เราคิดซ้ำ ๆ ว่าข้อ จำกัด ของความรู้ทำให้เรายืนนิ่งและยากที่จะก้าวไปข้างหน้า
ในช่วงเวลานี้การบ้านการออกแบบหลักสูตรและรายงานการทดลองต่าง ๆ เพิ่มขึ้นเป็นสองเท่า มันเป็นเรื่องยากที่จะบีบเวลาเล็กน้อยอย่านอนหลับและจัดเรียงหนังสือที่ฉันเคยอ่านในอดีตเพื่อใกล้ชิดกับการเขียนห้องสมุดของตัวเองมากขึ้น
บทความนี้อ้างอิงจาก "Essence ภาษา JavaScript" และ "JavaScript ที่มีประสิทธิภาพ" ตัวอย่างทั้งหมดได้รับการแก้ไขข้อบกพร่อง หลังจากเข้าใจพวกเขาฉันต้องการสร้างหลักการ "ลึก" ให้ง่ายขึ้นเล็กน้อย
1. ขอบเขตตัวแปร
ขอบเขตเป็นเหมือนออกซิเจนไปยังโปรแกรมเมอร์ ทุกที่และคุณไม่ได้คิดถึงมัน แต่เมื่อมันปนเปื้อน (เช่นการใช้วัตถุทั่วโลก) คุณจะรู้สึกสำลัก (เช่นการตอบสนองแอปพลิเคชันช้า) กฎขอบเขตหลัก JavaScript นั้นง่ายออกแบบมาอย่างระมัดระวังและทรงพลังมาก การใช้ JavaScript อย่างมีประสิทธิภาพจำเป็นต้องมีการเรียนรู้แนวคิดพื้นฐานบางประการของขอบเขตตัวแปรและทำความเข้าใจกับสถานการณ์ที่รุนแรงบางอย่างที่อาจนำไปสู่ปัญหาที่เข้าใจยากและน่ารำคาญ
1.1 พยายามใช้ตัวแปรทั่วโลกให้น้อยที่สุด
JavaScript นั้นง่ายต่อการสร้างตัวแปรในเนมสเปซทั่วโลก การสร้างตัวแปรทั่วโลกนั้นง่ายดายเพราะไม่จำเป็นต้องมีการประกาศรูปแบบใด ๆ และสามารถเข้าถึงได้โดยอัตโนมัติโดยรหัสทั้งหมดของโปรแกรมทั้งหมด
สำหรับผู้เริ่มต้นของเราเมื่อพบกับความต้องการบางอย่าง (ตัวอย่างเช่นเมื่อมีการบันทึกข้อมูลที่ส่งผ่านให้รอเวลาที่จะถูกเรียกหรือเมื่อใช้ฟังก์ชั่นบางอย่าง) ในที่สุดเราก็นึกถึงฟังก์ชั่นทั่วโลก แม้แต่การคิดเชิงภาษา C ที่ฉันเรียนรู้ในปีแรกของฉันก็หยั่งรากลึกเกินไปและระบบก็เต็มไปด้วยฟังก์ชั่น การกำหนดตัวแปรทั่วโลกสามารถสร้างมลพิษให้กับเนมสเปซสาธารณะที่ใช้ร่วมกันและสามารถนำไปสู่ความขัดแย้งในการตั้งชื่อที่ไม่คาดคิด ตัวแปรทั่วโลกยังไม่เอื้อต่อการแยกส่วนเนื่องจากเป็นสาเหตุของการมีเพศสัมพันธ์ที่ไม่จำเป็นระหว่างส่วนประกอบอิสระในโปรแกรม การพูดอย่างจริงจังทั่วโลกมากเกินไป (รวมถึงแผ่นสไตล์การกำหนดรูปแบบของ div หรือ a) โดยตรงและการรวมเข้ากับการพัฒนาของผู้คนหลายคนจะเป็นความผิดพลาดที่หายนะ นี่คือเหตุผลที่รหัส jQuery ทั้งหมดถูกห่อหุ้มด้วยนิพจน์นิรนามที่ดำเนินการทันที - ฟังก์ชั่นที่ไม่ระบุชื่อด้วยตนเอง เมื่อเบราว์เซอร์โหลดไฟล์ jQuery มันจะเริ่มดำเนินการทันทีหลังจากเรียกฟังก์ชั่นที่ไม่ระบุชื่อให้เริ่มต้นโมดูลต่าง ๆ ของ jQuery เพื่อหลีกเลี่ยงการทำลายและสร้างมลพิษตัวแปรทั่วโลกและส่งผลกระทบต่อรหัสอื่น ๆ
การคัดลอกรหัสมีดังนี้:
(ฟังก์ชั่น (หน้าต่างที่ไม่ได้กำหนด) {
var jQuery = ...
-
window.jQuery = window. $ = jQuery;
})(หน้าต่าง);
นอกจากนี้คุณอาจคิดว่ามันสะดวกกว่าที่จะ "เขียนวิธีการที่คุณเป็นอันดับแรกและจัดระเบียบในภายหลัง" แต่โปรแกรมเมอร์ที่ยอดเยี่ยมจะให้ความสนใจกับโครงสร้างของโปรแกรมอย่างต่อเนื่องจัดประเภทฟังก์ชั่นที่เกี่ยวข้องอย่างต่อเนื่องและแยกส่วนประกอบที่ไม่เกี่ยวข้องและพฤติกรรมเหล่านี้เป็นส่วนหนึ่งของสูตรการเขียนโปรแกรม
เนื่องจากเนมสเปซทั่วโลกเป็นวิธีเดียวสำหรับส่วนประกอบอิสระในโปรแกรม JavaScript ในการโต้ตอบการใช้การควบคุมการตั้งชื่อทั่วโลกจึงหลีกเลี่ยงไม่ได้ ส่วนประกอบหรือห้องสมุดต้องกำหนดตัวแปรทั่วโลก สำหรับใช้งานโดยส่วนอื่น ๆ ของโปรแกรม มิฉะนั้นจะเป็นการดีที่สุดที่จะใช้ตัวแปรท้องถิ่น
การคัดลอกรหัสมีดังนี้:
this.foo; // undefined
foo = "Global Foo";
this.foo; // "global foo"
var foo = "global foo";
this.foo = "เปลี่ยน";
foo; // เปลี่ยนไป
เนมสเปซทั่วโลกของ JavaScript ยังสัมผัสกับวัตถุระดับโลกที่สามารถเข้าถึงได้ในขอบเขตทั่วโลกของโปรแกรมซึ่งทำหน้าที่เป็นค่าเริ่มต้นของคำหลักนี้ ในเว็บเบราว์เซอร์วัตถุทั่วโลกจะถูกผูกไว้กับตัวแปรหน้าต่างทั่วโลก ซึ่งหมายความว่ามีสองวิธีในการสร้างตัวแปรทั่วโลก: ประกาศด้วย VAR ภายในขอบเขตส่วนกลางหรือเพิ่มลงในวัตถุส่วนกลาง ข้อได้เปรียบของการใช้การประกาศ VAR คือพวกเขาสามารถแสดงผลกระทบของตัวแปรทั่วโลกในขอบเขตของโปรแกรมได้อย่างชัดเจน
เนื่องจากการอ้างอิงถึงตัวแปรทั่วโลกที่ถูกผูกไว้อาจทำให้เกิดข้อผิดพลาดรันไทม์ขอบเขตการบันทึกที่ชัดเจนและรัดกุมจะทำให้ผู้ใช้โค้ดเข้าใจตัวแปรทั่วโลกที่โปรแกรมประกาศได้ง่ายขึ้น
เนื่องจากวัตถุระดับโลกมีกลไกการตอบสนองแบบไดนามิกสำหรับสภาพแวดล้อมระดับโลกจึงสามารถใช้ในการสอบถามสภาพแวดล้อมที่กำลังทำงานและตรวจจับคุณสมบัติที่มีอยู่ในแพลตฟอร์มนี้
เช่น. ES5 แนะนำวัตถุ JSON ทั่วโลกในการอ่านและเขียนข้อมูลรูปแบบ JSON
การคัดลอกรหัสมีดังนี้:
ถ้า (! this.json) {
this.json = {
แยกวิเคราะห์: .. ,
Stringify: ...
-
-
หากคุณให้การดำเนินการของ JSON คุณสามารถใช้การใช้งานของคุณเองได้อย่างง่ายดายและไม่มีเงื่อนไข แต่การใช้งานในตัวที่จัดทำโดยสภาพแวดล้อมของโฮสต์นั้นเกือบจะเหมาะสมกว่าเพราะพวกเขาเขียนลงในเบราว์เซอร์ใน C. เพราะพวกเขาตรวจสอบความถูกต้องและความสอดคล้องอย่างเคร่งครัดตามมาตรฐานบางอย่างและโดยทั่วไปให้ประสิทธิภาพที่ดีกว่าการใช้งานของบุคคลที่สาม
การดำเนินการพื้นฐานของสตริงการออกแบบหลักสูตรการออกแบบโครงสร้างข้อมูลจำเป็นต้องใช้วิธีการที่ได้รับจากภาษาเอง JavaScript ใช้การดำเนินการพื้นฐานของอาร์เรย์เป็นอย่างดี หากเป็นเพียงความต้องการการเรียนรู้ทั่วไปแนวคิดของวิธีการจำลองที่ได้รับจากภาษานั้นดี แต่ถ้าคุณลงทุนในการพัฒนาจริง ๆ คุณไม่จำเป็นต้องพิจารณาเลือกใช้วิธีการในตัว JavaScript โดยเร็วที่สุด
1.2 หลีกเลี่ยงการใช้กับ
คำสั่งพร้อมให้ "ความสะดวกสบาย" ใด ๆ ที่ทำให้แอปพลิเคชันของคุณไม่น่าเชื่อถือและไม่มีประสิทธิภาพ เราจำเป็นต้องเรียกชุดของวิธีการบนวัตถุเดียวในทางกลับกัน การใช้คำสั่งด้วยสามารถหลีกเลี่ยงการอ้างอิงที่ซ้ำกันกับวัตถุ:
การคัดลอกรหัสมีดังนี้:
สถานะฟังก์ชัน (ข้อมูล) {
var widget = widget ใหม่ ();
ด้วย (วิดเจ็ต) {
Fetbackground ("Blue");
setforeground ("สีขาว");
setText ("สถานะ:"+ข้อมูล);
แสดง();
-
-
นอกจากนี้ยังเป็นสิ่งดึงดูดอย่างมากที่จะใช้คำสั่งกับตัวแปร "นำเข้า" (นำเข้า) จากวัตถุโมดูล
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น f (x, y) {
ด้วย (คณิตศาสตร์) {
return min (รอบ (x), sqrt (y)); // บทคัดย่อใบเสนอราคา
-
-
ในความเป็นจริง JavaScript ปฏิบัติต่อตัวแปรทั้งหมดเหมือนกัน JavaScript เริ่มต้นจากขอบเขตด้านในสุดและมองหาตัวแปรออกไปด้านนอก ด้วยภาษาที่ปฏิบัติต่อวัตถุราวกับว่ามันแสดงถึงขอบเขตตัวแปรดังนั้นภายในบล็อกด้วยรหัสด้วยการค้นหาตัวแปรเริ่มต้นด้วยการค้นหาแอตทริบิวต์ของชื่อตัวแปรที่กำหนด หากไม่พบคุณสมบัติในวัตถุนี้ให้ค้นหาในขอบเขตภายนอกต่อไป การอ้างอิงถึงตัวแปรภายนอกแต่ละตัวในบล็อกที่มีโดยปริยายถือว่าไม่มีแอตทริบิวต์ที่มีชื่อเดียวกันในวัตถุที่มี (และวัตถุต้นแบบใด ๆ ) การสร้างหรือแก้ไขวัตถุด้วยหรือต้นแบบที่อื่นในโปรแกรมไม่จำเป็นต้องปฏิบัติตามสมมติฐานดังกล่าว เอ็นจิ้น JavaScript ไม่ได้อ่านรหัสท้องถิ่นเพื่อรับตัวแปรท้องถิ่นที่คุณใช้ ขอบเขต JavaScript สามารถแสดงเป็นโครงสร้างข้อมูลภายในที่มีประสิทธิภาพและการค้นหาตัวแปรนั้นเร็วมาก อย่างไรก็ตามเนื่องจากบล็อกด้วยรหัสด้วยจำเป็นต้องค้นหาห่วงโซ่ต้นแบบของวัตถุเพื่อค้นหาตัวแปรทั้งหมดในรหัสด้วยความเร็วการทำงานของมันจึงต่ำกว่าของบล็อกรหัสทั่วไปมาก
แทนที่จะใช้ภาษาด้วยภาษามันง่ายที่จะผูกวัตถุกับชื่อตัวแปรสั้น ๆ
การคัดลอกรหัสมีดังนี้:
สถานะฟังก์ชัน (ข้อมูล) {
var w = widget ใหม่ ();
W.SetBackground ("Blue");
W.Setforeground ("สีขาว");
W.Settext ("สถานะ:"+ข้อมูล);
w.show ();
-
ในกรณีอื่น ๆ วิธีที่ดีที่สุดคือการผูกตัวแปรท้องถิ่นกับคุณสมบัติที่เกี่ยวข้องอย่างชัดเจน
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น f (x, y) {
var min = math.min
round = math.round
sqrt = math.sqrt;
return min (รอบ (x), sqrt (y));
-
1.3 มีความเชี่ยวชาญในการปิด
มีแนวคิดเดียวที่จะเข้าใจการปิด:
A) JavaScript อนุญาตให้คุณอ้างอิงตัวแปรที่กำหนดไว้นอกฟังก์ชั่นปัจจุบัน
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น makeandwich () {
var magicingredient = "เนยถั่ว";
ฟังก์ชั่นทำ (เติม) {
คืนเวทมนตร์ + "และ" + เติม;
-
Return Make ("Jelly");
-
Makeandwich (); // "เนยถั่วและเยลลี่"
b) แม้ว่าฟังก์ชั่นภายนอกจะส่งคืนฟังก์ชั่นปัจจุบันยังสามารถอ้างถึงตัวแปรที่กำหนดโดยฟังก์ชันภายนอก
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น makeandwich () {
var magicingredient = "เนยถั่ว";
ฟังก์ชั่นทำ (เติม) {
คืนเวทมนตร์ + "และ" + เติม;
-
กลับมาทำ;
-
var f = sandwichmaker ();
f ("เยลลี่"); // "เนยถั่วและเยลลี่"
F ("กล้วย"); // "เนยถั่วและกล้วย"
F ("Mallows"); // "เนยถั่วและ mallows"
ค่าฟังก์ชั่นของ JavaScriptD มีข้อมูลมากกว่ารหัสที่จำเป็นในการเรียกใช้งานเมื่อถูกเรียก ยิ่งไปกว่านั้นค่าฟังก์ชัน JavaScript ยังเก็บตัวแปรภายในที่พวกเขาอาจอ้างถึงที่กำหนดไว้ในขอบเขตที่แนบมา ฟังก์ชั่นเหล่านั้นที่ติดตามตัวแปรภายในขอบเขตที่ครอบคลุมเรียกว่าปิด
ฟังก์ชั่น Make คือการปิดรหัสที่หมายถึงตัวแปรภายนอกสองตัว: Magicingredient และการเติม เมื่อใดก็ตามที่เรียกใช้ฟังก์ชัน Make รหัสของมันสามารถอ้างถึงตัวแปรทั้งสองนี้เนื่องจากการปิดเก็บตัวแปรทั้งสองนี้
ฟังก์ชั่นสามารถอ้างถึงตัวแปรใด ๆ ภายในขอบเขตรวมถึงพารามิเตอร์และตัวแปรฟังก์ชันภายนอก เราสามารถใช้สิ่งนี้เพื่อเขียนฟังก์ชั่น Sandwichmaker ทั่วไปมากขึ้น
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น makeandwich (Magicingredient) {
ฟังก์ชั่นทำ (เติม) {
คืนเวทมนตร์ + "และ" + เติม;
-
กลับมาทำ;
-
var f = Sandwichmaker ("Ham");
F ("ชีส"); // "แฮมและชีส"
F ("มัสตาร์ด"); // "แฮมและมัสตาร์ด"
การปิดเป็นหนึ่งในคุณสมบัติที่หรูหราและแสดงออกที่สุดของ JavaScript และยังเป็นแกนหลักของสำนวนมากมาย
c) การปิดสามารถอัปเดตค่าของตัวแปรภายนอก ในความเป็นจริงการปิดร้านค้าการอ้างอิงไปยังตัวแปรภายนอกไม่ใช่สำเนาของค่าของพวกเขา ดังนั้นการปิดใด ๆ ที่มีการเข้าถึงตัวแปรภายนอกเหล่านี้สามารถอัปเดตได้
การคัดลอกรหัสมีดังนี้:
กล่องฟังก์ชัน () {
var val = ไม่ได้กำหนด;
กลับ {
ชุด: ฟังก์ชั่น (newVal) {val = newVal;},
รับ: function () {return val;},
ประเภท: function () {return typeof val;}
-
-
var b = box ();
B.Type (); // ไม่ได้กำหนด
b.set (98.6);
b.get (); // 98.6
b.type (); // จำนวน
ตัวอย่างนี้สร้างวัตถุที่มีการปิดสามครั้ง การปิดทั้งสามนี้ได้รับการตั้งค่าพิมพ์และรับคุณสมบัติและพวกเขาทั้งหมดแชร์การเข้าถึงตัวแปร VAL และการปิดชุดอัปเดตค่าของ VAL จากนั้นโทรหาและพิมพ์เพื่อดูผลลัพธ์ที่อัปเดต
1.4 เข้าใจการปรับปรุงการประกาศตัวแปร
JavaScript รองรับขอบเขตวิธีนี้ (การอ้างอิงถึงตัวแปร FOO จะถูกผูกไว้กับขอบเขตที่ประกาศใกล้เคียงกับตัวแปร FOO ที่ใกล้เคียงที่สุด) แต่ไม่รองรับขอบเขตระดับบล็อก (ขอบเขตที่กำหนดโดยตัวแปรไม่ใช่คำสั่งปิดหรือบล็อกรหัสที่ใกล้เคียงที่สุด)
การไม่เข้าใจคุณสมบัตินี้จะนำไปสู่ข้อบกพร่องที่ละเอียดอ่อนบางอย่าง:
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น iswinner (ผู้เล่น, อื่น ๆ ) {
var สูงสุด = 0;
สำหรับ (var i = 0, n = อื่น ๆ ความยาว; i <n; i ++) {
var player = อื่น ๆ [i];
if (player.score> สูงสุด) {
สูงสุด = player.score;
-
-
return player.score> สูงสุด;
-
1.5 ระวังขอบเขตที่ซุ่มซ่ามของนิพจน์ฟังก์ชั่นการตั้งชื่อ
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น double (x) {return x*2; -
var f = function (x) {return x*2; -
รหัสฟังก์ชั่นชิ้นเดียวกันสามารถใช้เป็นนิพจน์ได้ แต่มีความหมายที่แตกต่างกันอย่างสิ้นเชิง ความแตกต่างอย่างเป็นทางการระหว่างฟังก์ชั่นที่ไม่ระบุชื่อและการแสดงออกของฟังก์ชั่นที่มีชื่อคือหลังถูกผูกไว้กับตัวแปรที่มีชื่อฟังก์ชั่นเดียวกับชื่อฟังก์ชันซึ่งทำหน้าที่เป็นตัวแปรท้องถิ่นของฟังก์ชั่น สิ่งนี้สามารถใช้ในการเขียนนิพจน์ฟังก์ชั่นแบบเรียกซ้ำได้
การคัดลอกรหัสมีดังนี้:
var f = ฟังก์ชั่นค้นหา (ต้นไม้, ปุ่ม) {
-
Return find (tree.left, key) ||
ค้นหา (tree.right, key);
-
เป็นที่น่าสังเกตว่าขอบเขตของการค้นหาตัวแปรนั้นอยู่ในฟังก์ชั่นของตัวเองเท่านั้น ซึ่งแตกต่างจากการประกาศฟังก์ชั่นการแสดงออกของฟังก์ชั่นที่มีชื่อไม่สามารถอ้างอิงภายนอกผ่านชื่อฟังก์ชั่นภายใน
การคัดลอกรหัสมีดังนี้:
ค้นหา (mytree, "foo"); // ข้อผิดพลาด: ค้นหาไม่ได้กำหนด;
var constructor = function () {return null; -
var f = function () {
return constructor ();
-
f (); // {} (ในสภาพแวดล้อม ES3)
โปรแกรมดูเหมือนว่ามันจะเป็นโมฆะ แต่จริง ๆ แล้วมันจะสร้างวัตถุใหม่
เนื่องจากตัวแปรฟังก์ชั่นที่มีชื่อสืบทอด Object.prototype.constructor (เช่นตัวสร้างของ Oject) เช่นเดียวกับคำสั่งขอบเขตนี้จะได้รับผลกระทบจากการเปลี่ยนแปลงแบบไดนามิกของ Object.prototype วิธีที่จะหลีกเลี่ยงวัตถุที่ปนเปื้อนขอบเขตของการแสดงออกของฟังก์ชั่นในระบบคือการหลีกเลี่ยงการเพิ่มคุณสมบัติใน object.prototype ได้ตลอดเวลาเพื่อหลีกเลี่ยงการใช้ตัวแปรท้องถิ่นใด ๆ ที่มีชื่อเดียวกับคุณสมบัติวัตถุมาตรฐาน prototype
ข้อเสียอีกประการหนึ่งในเอ็นจิ้น JavaScript ยอดนิยมคือการส่งเสริมการประกาศการแสดงออกของฟังก์ชั่นที่มีชื่อ
การคัดลอกรหัสมีดังนี้:
var f = function g () {return 17;}
g (); // 17 (ในสภาพแวดล้อมที่ไม่เป็นไปตามกฎหมาย)
สภาพแวดล้อม JavaScript บางตัวยังใช้ฟังก์ชั่นทั้งสอง F และ G เป็นวัตถุที่แตกต่างกันส่งผลให้เกิดการจัดสรรหน่วยความจำที่ไม่จำเป็น
1.6 ระวังขอบเขตเงอะงะสำหรับฟังก์ชั่นบล็อกท้องถิ่น
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น f () {return "global"; -
การทดสอบฟังก์ชั่น (x) {
ฟังก์ชัน f () {return "local";}
var result = [];
ถ้า (x) {
result.push (f ());
-
result.push (f ());
ผลลัพธ์ผลลัพธ์
-
ทดสอบ (จริง); // ["ท้องถิ่น", "ท้องถิ่น"]
ทดสอบ (เท็จ); //["ท้องถิ่น"]
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น f () {return "global"; -
การทดสอบฟังก์ชั่น (x) {
var result = [];
ถ้า (x) {
ฟังก์ชัน f () {return "local";}
result.push (f ());
-
result.push (f ());
ผลลัพธ์ผลลัพธ์
-
ทดสอบ (จริง); // ["ท้องถิ่น", "ท้องถิ่น"]
ทดสอบ (เท็จ); //["ท้องถิ่น"]
JavaScript ไม่มีขอบเขตระดับบล็อกดังนั้นขอบเขตของฟังก์ชั่นภายใน f ควรเป็นฟังก์ชันการทดสอบทั้งหมด สภาพแวดล้อม JavaScript บางตัวทำ แต่สภาพแวดล้อม JavaScript ทั้งหมดไม่ได้ทำ รายงานการใช้งาน JavaScript ฟังก์ชั่นเช่นข้อผิดพลาดในโหมดที่เข้มงวด (โปรแกรมในโหมดเข้มงวดพร้อมการประกาศฟังก์ชั่นบล็อกท้องถิ่นจะรายงานว่าเป็นข้อผิดพลาดทางไวยากรณ์) ซึ่งช่วยตรวจจับรหัสที่ไม่สามารถพกพาได้ ในกรณีนี้เป็นไปได้ที่จะพิจารณาประกาศตัวแปรท้องถิ่นภายในฟังก์ชั่นทดสอบเพื่อชี้ไปที่ฟังก์ชั่นทั่วโลก f