“ โหมดเข้มงวด” คืออะไรและใช้อย่างไร


137

ฉันได้รับการมองข้ามอ้างอิง JavaScript ด้านพัฒนาเครือข่าย Mozilla"strict mode"และฉันมาข้ามสิ่งที่เรียกว่า ฉันอ่านจบแล้วและฉันมีปัญหาในการทำความเข้าใจว่ามันทำอะไร ใครสามารถอธิบายสั้น ๆ (โดยทั่วไป) ว่าจุดประสงค์คืออะไรและมีประโยชน์อย่างไร?


2
ที่เกี่ยวข้อง: stackoverflow.com/q/1335851/1461424
sampathsris

คำตอบ:


152

จุดประสงค์หลักคือการตรวจสอบเพิ่มเติม

เพียงเพิ่ม"use strict";ที่ด้านบนของรหัสของคุณก่อนสิ่งอื่นใด

ตัวอย่างเช่นblah = 33;JavaScript ที่ถูกต้อง blahมันหมายความว่าคุณสร้างตัวแปรทั่วโลกอย่างสมบูรณ์

แต่ในโหมดเข้มงวดจะเกิดข้อผิดพลาดเนื่องจากคุณไม่ได้ใช้คีย์เวิร์ด "var" เพื่อประกาศตัวแปร

เวลาส่วนใหญ่คุณไม่ได้ตั้งใจที่จะสร้างตัวแปรส่วนกลางในขอบเขตที่กำหนดเองดังนั้นเวลาส่วนใหญ่ที่blah = 33เขียนมันเป็นข้อผิดพลาดและโปรแกรมเมอร์ไม่ต้องการให้เป็นตัวแปรส่วนกลาง เขียนvar blah = 33.

ในทำนองเดียวกันไม่อนุญาตให้ทำหลายสิ่งหลายอย่างที่สามารถทำได้ในทางเทคนิค NaN = "lol"ไม่ก่อให้เกิดข้อผิดพลาด นอกจากนี้ยังไม่เปลี่ยนแปลงค่าของ NaN การใช้คำสั่ง (และข้อความแปลก ๆ ที่คล้ายกัน) อย่างเข้มงวดทำให้เกิดข้อผิดพลาด คนส่วนใหญ่ชื่นชมสิ่งนี้เพราะไม่มีเหตุผลที่จะต้องเขียนNaN = "lol"จึงมีแนวโน้มที่จะพิมพ์ผิด

อ่านเพิ่มเติมได้ที่หน้า MDN ในโหมดที่เข้มงวด


4
นี่เป็นเอกสารที่ซ้ำกันทุก
ประการ

23
คุณไม่เข้าใจอะไรเกี่ยวกับยูทิลิตี้ของมัน? มีจุดมุ่งหมายเพื่อช่วยในการพัฒนาโดยการจับสิ่งที่ถูกต้อง แต่มีโอกาสเกิดข้อผิดพลาดมากที่สุด
Simon Sarris

คำว่า"ใช้คำว่าเข้มงวดนี้"หมายความว่าอย่างไร
Peter Mortensen

35

แง่มุมหนึ่งของโหมดเข้มงวดที่ไม่ได้กล่าวถึงในคำตอบของ Simon คือโหมดที่เข้มงวดตั้งค่าthisเป็นundefinedในฟังก์ชันที่เรียกใช้ผ่านการเรียกใช้ฟังก์ชัน

ดังนั้นสิ่งนี้

function Obj() {
   this.a = 12;
   this.b = "a";
   this.privilegedMethod = function () {
      this.a++;
      privateMethod();
   };

   function privateMethod() {
     this.b = "foo";
   }
}

จะทำให้เกิดข้อผิดพลาดเมื่อprivateMethodถูกเรียก (เนื่องจากคุณไม่สามารถเพิ่มคุณสมบัติให้ได้undefined) แทนที่จะเพิ่มbคุณสมบัติให้กับวัตถุส่วนกลางอย่างไร้ประโยชน์


4
ใช่ต้องเพิ่มprivateMethod.bind(this)();และโทรด้วยnew jsbin.com
hlcs

ข้อ จำกัด ที่สำคัญที่สุดในโหมดเข้มงวด: docs.microsoft.com/en-us/scripting/javascript/advanced/…
Krishna Mohan

23

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

Harmonyซึ่งหวังว่าจะกลายเป็น ECMAScript เวอร์ชันหลักถัดไปจะถูกสร้างขึ้นบน ES5 ที่เข้มงวด

Harmony สร้างในโหมดเข้มงวด ES5 เพื่อหลีกเลี่ยงโหมดที่มากเกินไป

การทดลองภาษาอื่น ๆ บางอย่างขึ้นอยู่กับโหมดเข้มงวด SESขึ้นอยู่กับการวิเคราะห์ของโหมด ES5 ที่เข้มงวด

SES (Secure ECMAScript) การออกแบบการทดลอง

ออกแบบ Object Capability Programming Language โดยการลบหรือซ่อมแซมคุณสมบัติใน ES5 / Strict

ควรมีการแปลแบบตรงไปตรงมาจาก SES เป็น ES5 / Strict

ภาคผนวก Cของมาตรฐานอธิบายความแตกต่างระหว่างโหมดเข้มงวดและโหมดปกติ

ข้อ จำกัด และข้อยกเว้นของโหมดที่เข้มงวด

  • ตัวระบุ "implements", "interface", "let", "package", "private", "protected", "public", "static" และ "yield" จัดเป็นโทเค็น FutureReservedWord ภายในโค้ดโหมดที่เข้มงวด (7.6.12 [?])
  • การใช้งานที่สอดคล้องกันเมื่อประมวลผลโค้ดโหมดเข้มงวดไม่สามารถขยายไวยากรณ์ของ NumericLiteral (7.8.3) เพื่อรวม OctalIntegerLiteral ตามที่อธิบายไว้ใน B.1.1
  • การใช้งานที่สอดคล้องกันเมื่อประมวลผลโค้ดโหมดเข้มงวด (ดูข้อ 10.1.1) ไม่สามารถขยายไวยากรณ์ของ EscapeSequence เพื่อรวม OctalEscapeSequence ตามที่อธิบายไว้ใน B.1.2
  • การกำหนดให้กับตัวระบุที่ไม่ได้ประกาศหรือการอ้างอิงที่ไม่สามารถแก้ไขได้จะไม่สร้างคุณสมบัติในอ็อบเจ็กต์ส่วนกลาง เมื่อการกำหนดอย่างง่ายเกิดขึ้นภายในโค้ดโหมดที่เข้มงวด LeftHandSide ต้องไม่ประเมินเป็นการอ้างอิงที่ไม่สามารถแก้ไขได้ หากทำข้อยกเว้น ReferenceError จะถูกโยนทิ้ง (8.7.2) LeftHandSide อาจไม่ใช่การอ้างอิงถึงคุณสมบัติข้อมูลที่มีค่าแอตทริบิวต์ {[[Writable]]: false} ไปยังคุณสมบัติ accessor ที่มีค่าแอตทริบิวต์ {[[Set]]: undefined} หรือเป็นค่าที่ไม่มีอยู่จริง คุณสมบัติของอ็อบเจ็กต์ที่มีคุณสมบัติภายใน [[Extensible]] มีค่าเป็นเท็จ ในกรณีเหล่านี้จะมีข้อยกเว้น TypeError (11.13.1)
  • ตัวระบุ eval หรืออาร์กิวเมนต์ต้องไม่ปรากฏเป็น LeftHandSideExpression ของตัวดำเนินการ Assignment (11.13) หรือของ PostfixExpression (11.3) หรือเป็น UnaryExpression ที่ดำเนินการโดย Prefix Increment (11.4.4) หรือ Prefix Decrement (11.4.5) . อ็อบเจ็กต์อาร์กิวเมนต์สำหรับฟังก์ชันโหมดเข้มงวดกำหนดคุณสมบัติตัวเข้าถึงที่ไม่สามารถกำหนดค่าได้ชื่อ "caller" และ "callee" ซึ่งทำให้เกิดข้อยกเว้น TypeError ในการเข้าถึง (10.6)
  • อ็อบเจ็กต์อาร์กิวเมนต์สำหรับฟังก์ชันโหมดเข้มงวดไม่แชร์ค่าคุณสมบัติที่จัดทำดัชนีอาร์เรย์แบบไดนามิกกับการเชื่อมโยงพารามิเตอร์ที่เป็นทางการที่สอดคล้องกันของฟังก์ชัน (10.6) สำหรับฟังก์ชันโหมดที่เข้มงวดหากอ็อบเจ็กต์อาร์กิวเมนต์ถูกสร้างขึ้นการเชื่อมโยงของอาร์กิวเมนต์ตัวระบุโลคัลกับอ็อบเจ็กต์อาร์กิวเมนต์จะไม่เปลี่ยนรูปและด้วยเหตุนี้จึงอาจไม่ใช่เป้าหมายของนิพจน์การกำหนด (10.5)
  • เป็น SyntaxError หากโค้ดโหมดเข้มงวดมี ObjectLiteral ที่มีคำจำกัดความของคุณสมบัติข้อมูลมากกว่าหนึ่งรายการ (11.1.5) เป็น SyntaxError ถ้าตัวระบุ "eval" หรือ "อาร์กิวเมนต์" ตัวระบุเกิดขึ้นเป็นตัวระบุใน PropertySetParameterList ของ PropertyAssignment ที่มีอยู่ในโค้ดที่เข้มงวดหรือถ้า FunctionBody เป็นรหัสที่เข้มงวด (11.1.5)
  • รหัส eval โหมดเข้มงวดไม่สามารถสร้างอินสแตนซ์ตัวแปรหรือฟังก์ชันในสภาพแวดล้อมตัวแปรของผู้เรียกเพื่อประเมิน แต่สภาพแวดล้อมตัวแปรใหม่จะถูกสร้างขึ้นและสภาพแวดล้อมนั้นถูกใช้สำหรับการประกาศการเชื่อมโยงอินสแตนซ์สำหรับโค้ด eval (10.4.2)
  • หากค่านี้ได้รับการประเมินภายในโค้ดโหมดเข้มงวดค่านี้จะไม่ถูกบังคับให้ออบเจ็กต์ ค่าว่างหรือไม่ได้กำหนดนี้จะไม่ถูกแปลงเป็นอ็อบเจ็กต์ส่วนกลางและค่าดั้งเดิมจะไม่ถูกแปลงเป็นอ็อบเจ็กต์ wrapper ค่านี้ส่งผ่านการเรียกใช้ฟังก์ชัน (รวมถึงการเรียกโดยใช้ Function.prototype.apply และ Function.prototype.call) ไม่บังคับให้ส่งค่านี้ไปยังวัตถุ (10.4.3, 11.1.1, 15.3.4.3, 15.3 4.4)
  • เมื่อตัวดำเนินการลบเกิดขึ้นภายในโค้ดโหมดที่เข้มงวด SyntaxError จะปรากฏขึ้นหาก UnaryExpression เป็นการอ้างอิงโดยตรงไปยังตัวแปรอาร์กิวเมนต์ของฟังก์ชันหรือชื่อฟังก์ชัน (11.4.1)
  • เมื่อตัวดำเนินการลบเกิดขึ้นภายในโค้ดโหมดที่เข้มงวด TypeError จะปรากฏขึ้นหากคุณสมบัติที่จะลบมีแอตทริบิวต์ {[[Configurable]]: false} (11.4.1) เป็น SyntaxError ถ้า VariableDeclaration หรือ VariableDeclarationNoIn เกิดขึ้นภายในโค้ดที่เข้มงวดและ Identifier เป็น eval หรืออาร์กิวเมนต์ (12.2.1)
  • รหัสโหมดเข้มงวดต้องไม่มี WithStatement การเกิด WithStatement ในบริบทดังกล่าวคือ SyntaxError (12.10)
  • มันเป็น SyntaxError หาก TryStatement ที่มี Catch เกิดขึ้นภายในโค้ดที่เข้มงวดและตัวระบุของการผลิต Catch คือ eval หรืออาร์กิวเมนต์ (12.14.1)
  • เป็น SyntaxError ถ้าตัวระบุ eval หรืออาร์กิวเมนต์ปรากฏใน FormalParameterList ของโหมดเข้มงวด FunctionDeclaration หรือ FunctionExpression (13.1)
  • ฟังก์ชันโหมดเข้มงวดอาจไม่มีพารามิเตอร์ที่เป็นทางการสองตัวหรือมากกว่าที่มีชื่อเดียวกัน ความพยายามที่จะสร้างฟังก์ชันดังกล่าวโดยใช้ FunctionDeclaration, FunctionExpression หรือตัวสร้างฟังก์ชันคือ SyntaxError (13.1, 15.3.2)
  • การนำไปใช้งานต้องไม่ขยายออกไปนอกเหนือจากที่กำหนดไว้ในข้อกำหนดนี้ความหมายภายในฟังก์ชันโหมดเข้มงวดของคุณสมบัติที่ชื่อผู้เรียกหรืออาร์กิวเมนต์ของอินสแตนซ์ฟังก์ชัน รหัส ECMAScript ไม่สามารถสร้างหรือแก้ไขคุณสมบัติด้วยชื่อเหล่านี้บนวัตถุฟังก์ชันที่สอดคล้องกับฟังก์ชันโหมดเข้มงวด (10.6, 13.2, 15.3.4.5.3)
  • เป็น SyntaxError เพื่อใช้ภายในโค้ดโหมดที่เข้มงวดตัวระบุประเมินหรืออาร์กิวเมนต์เป็นตัวระบุของ FunctionDeclaration หรือ FunctionExpression หรือเป็นชื่อพารามิเตอร์ที่เป็นทางการ (13.1) การพยายามกำหนดฟังก์ชันโหมดเข้มงวดแบบไดนามิกโดยใช้ตัวสร้างฟังก์ชัน (15.3.2) จะทำให้เกิดข้อยกเว้น SyntaxError

7

ECMAScript 5 นำแนวคิดของโหมดที่เข้มงวด

เรียกใช้โหมดเข้มงวดในรหัส

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

สคริปต์ทั้งหมด:

สมมติว่าเรากำลังสร้าง app.js ดังนั้นการเพิ่มสคริปต์การใช้คำสั่งแรกจะบังคับใช้โหมดเข้มงวดสำหรับโค้ดทั้งหมด

// app.js whole script in strict mode syntax
“use strict”;
// Now you can start writing your code

โหมดเข้มงวดสำหรับฟังก์ชัน:

ในการเรียกใช้โหมดเข้มงวดสำหรับฟังก์ชันให้ใส่คำสั่งที่แน่นอนว่า "ใช้อย่างเข้มงวด"; ที่จุดเริ่มต้นของร่างกายฟังก์ชันก่อนคำสั่งอื่น ๆ

function yourFunc(){
    "use strict";

    // Your function code logic
}

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

สำหรับอินสแตนซ์: โค้ดโดยใช้โหมดเข้มงวด

ใส่คำอธิบายภาพที่นี่

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

ตอนนี้เรามาลองเข้าถึงตัวแปร x โดยไม่ต้องประกาศโดยไม่มีโหมดเข้มงวด

(function(){
    x = 3;
})();

// Will not throw an error

ข้อดีของการใช้โหมดเข้มงวด:

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

6

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

  • โหมดที่เข้มงวดช่วยขจัดข้อผิดพลาดที่เงียบของ JavaScript โดยการเปลี่ยนเป็นข้อผิดพลาด

  • โหมดเข้มงวดแก้ไขข้อผิดพลาดที่ทำให้เอ็นจิ้น JavaScript ดำเนินการเพิ่มประสิทธิภาพได้ยาก

  • โหมดเข้มงวดห้ามไม่ให้มีการกำหนดไวยากรณ์บางอย่างใน ECMAScript เวอร์ชันอนาคต


2

ECMAScript5 แนะนำออบเจ็กต์และคุณสมบัติใหม่ ๆ และสิ่งที่เรียกว่า "strict mode"แนะนำวัตถุใหม่บางและคุณสมบัติและยังเป็นสิ่งที่เรียกว่า

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

"use strict";

มันมากกว่าส่วนย่อยไม่ใช่เหรอ? เช่นเดียวกับการตรวจสอบตัวแปรที่ไม่ได้กำหนด?
Peter Mortensen

2

2017 และในที่สุดฉันก็พบเอกสาร:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode

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


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


0

คำถาม:

ต่อไปนี้เป็นปัญหาที่ฉันพบ ฉันกำลังติดตามบทช่วยสอนและลงเอยด้วยการพยายามรวบรวมscssไฟล์ต่อไปนี้และพยายามสร้างโค้ด CSS จากมัน

.fatty{
  width: percentage(6/7);
}

โดยใช้gulpfile.jsภารกิจต่อไปนี้:

var gulp = require('gulp');
var sass = require('gulp-sass');

gulp.task('sass', function () {
    return gulp.src('app/scss/styles.scss')
        .pipe(sass())
        .pipe(gulp.dest('app/css'))
});

ดังนั้นข้อผิดพลาดที่ฉันได้รับมีดังนี้:

~/htdocs/Learning/gulp1/node_modules/gulp-sass/index.js:66
    let sassMap;
    ^^^

SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:373:25)
// stacktrace here...

วิธีการแก้:

มันจะแสดงindex.jsไฟล์ที่อยู่ในโมดูล gulp-sass ของฉัน (ซึ่งโดยพื้นฐานแล้วจะถูกล็อคและไม่ควรแก้ไข) แต่ถ้าฉันใช้แรงและเพิ่มส่วน"use_strict"บนของindex.jsไฟล์นั้นมันจะทำงานได้อย่างราบรื่น

ฉันทำอะไรไม่ถูกเลยใช้วิธีนี้เป็นวิธีแก้ปัญหาต่อไป! แต่หลังจากผ่านQ & As ของ Stack Overflow อื่น ๆแล้วฉันก็เห็นคำตอบต่อไปนี้ดังนี้:

sudo npm install -g n
sudo n stable

และทันทีที่ฉันอัปเดต Node.js ของฉัน (เป็นเวอร์ชัน 10.x) จากนั้นสร้าง Gulp ขึ้นมาใหม่โดยเรียกใช้คำสั่งต่อไปนี้เป็น Terminal มันก็สั่งฉัน:

npm rebuild node-sass --force

และไม่เป็นไร นั่นคือวิธีที่ได้รับการแก้ไข ฉันได้ยกเลิกการเปลี่ยนแปลงที่ทำกับindex.jsไฟล์โมดูล Gulp.js และตอนนี้มันทำงานได้อย่างราบรื่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.