ฉันได้รับการมองข้ามอ้างอิง JavaScript ด้านพัฒนาเครือข่าย Mozilla"strict mode"
และฉันมาข้ามสิ่งที่เรียกว่า ฉันอ่านจบแล้วและฉันมีปัญหาในการทำความเข้าใจว่ามันทำอะไร ใครสามารถอธิบายสั้น ๆ (โดยทั่วไป) ว่าจุดประสงค์คืออะไรและมีประโยชน์อย่างไร?
ฉันได้รับการมองข้ามอ้างอิง JavaScript ด้านพัฒนาเครือข่าย Mozilla"strict mode"
และฉันมาข้ามสิ่งที่เรียกว่า ฉันอ่านจบแล้วและฉันมีปัญหาในการทำความเข้าใจว่ามันทำอะไร ใครสามารถอธิบายสั้น ๆ (โดยทั่วไป) ว่าจุดประสงค์คืออะไรและมีประโยชน์อย่างไร?
คำตอบ:
จุดประสงค์หลักคือการตรวจสอบเพิ่มเติม
เพียงเพิ่ม"use strict";
ที่ด้านบนของรหัสของคุณก่อนสิ่งอื่นใด
ตัวอย่างเช่นblah = 33;
JavaScript ที่ถูกต้อง blah
มันหมายความว่าคุณสร้างตัวแปรทั่วโลกอย่างสมบูรณ์
แต่ในโหมดเข้มงวดจะเกิดข้อผิดพลาดเนื่องจากคุณไม่ได้ใช้คีย์เวิร์ด "var" เพื่อประกาศตัวแปร
เวลาส่วนใหญ่คุณไม่ได้ตั้งใจที่จะสร้างตัวแปรส่วนกลางในขอบเขตที่กำหนดเองดังนั้นเวลาส่วนใหญ่ที่blah = 33
เขียนมันเป็นข้อผิดพลาดและโปรแกรมเมอร์ไม่ต้องการให้เป็นตัวแปรส่วนกลาง เขียนvar blah = 33
.
ในทำนองเดียวกันไม่อนุญาตให้ทำหลายสิ่งหลายอย่างที่สามารถทำได้ในทางเทคนิค NaN = "lol"
ไม่ก่อให้เกิดข้อผิดพลาด นอกจากนี้ยังไม่เปลี่ยนแปลงค่าของ NaN การใช้คำสั่ง (และข้อความแปลก ๆ ที่คล้ายกัน) อย่างเข้มงวดทำให้เกิดข้อผิดพลาด คนส่วนใหญ่ชื่นชมสิ่งนี้เพราะไม่มีเหตุผลที่จะต้องเขียนNaN = "lol"
จึงมีแนวโน้มที่จะพิมพ์ผิด
อ่านเพิ่มเติมได้ที่หน้า MDN ในโหมดที่เข้มงวด
แง่มุมหนึ่งของโหมดเข้มงวดที่ไม่ได้กล่าวถึงในคำตอบของ 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
คุณสมบัติให้กับวัตถุส่วนกลางอย่างไร้ประโยชน์
โหมดเข้มงวดถูกเพิ่มเข้ามาเพื่อให้มีชุดย่อยของ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
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 โดยการเปลี่ยนเป็นข้อผิดพลาด
โหมดเข้มงวดแก้ไขข้อผิดพลาดที่ทำให้เอ็นจิ้น JavaScript ดำเนินการเพิ่มประสิทธิภาพได้ยาก
โหมดเข้มงวดห้ามไม่ให้มีการกำหนดไวยากรณ์บางอย่างใน ECMAScript เวอร์ชันอนาคต
ECMAScript5
แนะนำออบเจ็กต์และคุณสมบัติใหม่ ๆ และสิ่งที่เรียกว่า "strict mode"
แนะนำวัตถุใหม่บางและคุณสมบัติและยังเป็นสิ่งที่เรียกว่า
โหมดเข้มงวดเป็นชุดย่อยของภาษาที่ไม่รวมคุณลักษณะที่เลิกใช้แล้ว โหมดที่เข้มงวดคือการเลือกใช้และไม่จำเป็นซึ่งหมายความว่าหากคุณต้องการให้โค้ดของคุณทำงานในโหมดเข้มงวดคุณต้องแสดงเจตนาโดยใช้ (หนึ่งครั้งต่อฟังก์ชันหรือหนึ่งครั้งสำหรับทั้งโปรแกรม) สตริงต่อไปนี้:
"use strict";
2017 และในที่สุดฉันก็พบเอกสาร:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
โหมดเข้มงวดเป็นวิธีเลือกใช้ JavaScript ในรูปแบบที่ จำกัด โหมดเข้มงวดไม่ได้เป็นเพียงส่วนย่อยเท่านั้น แต่มีเจตนาที่มีความหมายแตกต่างจากโค้ดปกติ เบราว์เซอร์ที่ไม่รองรับโหมดเข้มงวดจะเรียกใช้โค้ดโหมดที่เข้มงวดซึ่งมีลักษณะการทำงานแตกต่างจากเบราว์เซอร์ที่ทำดังนั้นอย่าพึ่งพาโหมดที่เข้มงวดโดยไม่มีการทดสอบคุณลักษณะเพื่อรองรับแง่มุมที่เกี่ยวข้องของโหมดเข้มงวด โค้ดโหมดเข้มงวดและโค้ดโหมดไม่เข้มงวดสามารถอยู่ร่วมกันได้ดังนั้นสคริปต์สามารถเลือกใช้โหมดเข้มงวดได้ทีละน้อย
โหมดเข้มงวดทำการเปลี่ยนแปลงหลายอย่างกับความหมายของ JavaScript ปกติ ขั้นแรกโหมดที่เข้มงวดจะกำจัดข้อผิดพลาดที่ไม่โต้ตอบของ JavaScript โดยการเปลี่ยนเป็นข้อผิดพลาด ประการที่สองโหมดเข้มงวดจะแก้ไขข้อผิดพลาดที่ทำให้เอ็นจิ้น JavaScript ดำเนินการเพิ่มประสิทธิภาพได้ยาก: บางครั้งโค้ดโหมดเข้มงวดอาจทำให้ทำงานได้เร็วกว่าโค้ดที่เหมือนกันซึ่งไม่ใช่โหมดที่เข้มงวด ประการที่สามโหมดเข้มงวดห้ามไม่ให้มีการกำหนดไวยากรณ์บางอย่างใน ECMAScript เวอร์ชันอนาคต
คำถาม:
ต่อไปนี้เป็นปัญหาที่ฉันพบ ฉันกำลังติดตามบทช่วยสอนและลงเอยด้วยการพยายามรวบรวม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 และตอนนี้มันทำงานได้อย่างราบรื่น