strict mode در جاوا اسکریپت ویژگی جدیدیه که در ECMAScript 5 معرفی شده و به شما اجازه میده یه برنامه یا یه عملکردی رو در فرم عملیاتی «StrictK» قرار بدین. این فرم Strict مانع انجام برخی اقدامات میشه و استثناهای بیشتری رو ایجاد میکنه. لاین «use strict» به مرورگر دستور میده از حالت Strict که یه مجموعه ویژگی کاهش یافته و ایمن از جاوا اسکریپت است، استفاده کنه.
پس مقاله امروز ما یه راهنمای کامل درمورد حالت سختگیرانه جاوا اسکریپت هست و این که این حالت دقیقاً چه کارهایی رو انجام میده و چه تفاوتی با جاوااسکریپت معمولی داره.
تا آخر مقاله همراه ما باشین تا به جواب سوالات خودتون برسین:
مزایای استفاده از strict mode در جاوا اسکریپت
حالت سختگیرانه یا همون strict mode چندین تغییر معنایی عادی در JavaScript ایجاد میکنه و علاوه بر این، مزایای زیر رو برای شما به وجود میاره:
- حالت سختگیرانه بعضی خطاهای ساکت JavaScript رو به وسیله تغییر اونها به پرتاب خطا از بین میبره.
- strict mode در جاوا اسکریپت خطاهایی که عملکرد بهینه سازی برای موتورهای JavaScript رو دشوار میکنه برطرف میکنه: گاهی وقتها کد حالت سخنگیرانه میتونه سریعتر از کد Identical که روی حالت Strict نیست، کار کنه.
- حالت سختگیرانه برخی از نحوهایی رو که احتمالاً در نسخههای بعدی ECMAScript تعریف میشن، ممنوع میکنه.
- وقتی اقدامات نسبتاً ناامنی انجام میشه (مانند دستیابی به هدف جهانی)، حالت Strict از این کار جلوگیری میکنه یا خطاهایی ایجاد میکنه.
- ویژگیهایی که گیج کننده هستن و یا ایده خوبی ندارن رو غیرفعال میکنه.
- حالت سخت نوشتن JavaScript امن رو آسون میکنه.
تا اینجای کار با حالت سخت و مزایای اون تا حدودی آشنا شدین پس الان لازمه که ببینین این حالت چطوری در جاوا اسکریپت استفاده میشه:
استفاده از حالت Strict mode جاوا اسکریپت
نحوه استفاده از strict mode در جاوا اسکریپت: حالت Strict رو میتونین به دو روش استفاده کنین، یادتون باشه که حالت سخت با عبارات بلوک محصور در براکت {} کار نمیکنه.
- در دامنه جهانی برای همه اسکریپتها استفاده میشه.
- میتونه برای توابع فردی اعمال بشه.
strict mode در دامنه جهانی
برای استفاده از حالت سخت JavaScript برای یه اسکریپت کامل، یا عبارت دقیق “use strict” یا ‘use strict’ رو قبل از هر عبارتی قرار بدین.
// Whole-script strict mode syntax
'use strict';
let v = "strict mode script!";
این نحو برای خودش یه جریانی داره، به هم پیوستن کورکورانه متنهای غیر متناقض ممکن نیست. ترکیب یه اسکریپت حالت سخت با یه اسکریپت حالت غیر سخت رو در نظر بگیرین. بهم پیوستگی این دو دقیق به نظر میرسه، برعکس این موضوع هم درسته.
حالت non-strict بعلاوه حالت Strict، غیر سخت (non-strict) به نظر میرسه. الحاق اسکریپت های حالت non-strict با همدیگه و الحالق اسکریپت های حالت strict باه دیگه کار درستیه و ایرادی نداره. فقط الحاق اسکریپت های سخت و غیر سخته که مسئله سازه. بنابراین توصیه ما اینه که حالت سختگیرانه رو بر اساس function-by-function (حداقل در دوره انتقال) فعال کنین.
استفاده از حالت strict mode برای یه تابع فردی
به همین ترتیب، برای فراخوانی حالت سختگیرانه برای یه تابع، عبارت دقیق “use strict” یا ‘use strict’ رو در بدنه تابع، قبل از هر عبارت دیگهای قرار بدین.
function strict() {
// Function-level strict mode syntax
'use strict';
function nested() { return 'Javascript on GeeksforGeeks'; }
return "strict mode function! " + nested();
}
function notStrict() { return "non strict function"; }
استفاده از حالت سخت JavaScript برای ماژول ها
ECMAScript در سال 2015 ماژول های JavaScript رو معرفی کرد. بنابراین، روش سوم فراخوانی حالت سخت به وجود اومد. در اینجا، همه محتوای ماژول های JavaScript به طور خودکار در حالت Strict قرار دارن و برای شروع اون به Statement نیازی نیست.
function strictFunc() {
// because this is a module, it is strict by default
console.log(“ the contents inside are automatically in strict mode”);
}
export default strictFunc;
در اینجا، ماژول تعریف شده به عنوان strictFunc، به طور خودکار در حالت سخت است و در نتیجه نیازی به استفاده از دستور “use strict” نیست.
حالت سختگیرانه در مرورگرها
در حال حاضر مرورگرهای اصلی مثل chrome ،Firefox ،opera و غیره strict mode در جاوا اسکریپت رو اجرا میکنن. با این حال، شما باید کورکورانه به اونها وابسته باشین. از اونجایی که هنوز نسخههای متعددی از مرورگرها در دنیا استفاده میشن که فقط یه پشتیبانی جزئی از حالت سخت میکنن یا این که اصلاً به هیچ وجه از اون پشتیبانی نمیکنن (به عنوان مثال اینترنت اکسپلورر در زیر نسخه 10)، پس باید حواستون باشه که از اونها با دقت در مرورگرها استفاده کنین.
همونطوری که قبلاً هم گفتیم حالت سخت یه سری تغییرات معنایی ایجاد میکنه. در نتیجه، تکیه بر این تغییرات باعث اشتباهات و خطاهایی در مرورگرهایی میشه که strict mode در جاوا اسکریپت رو اجرا نمیکنن. پس حرف ما اینه که شما باید در استفاده از این حالت احتیاط کنین و با آزمایش ویژگیهایی که بررسی میکنن آیا قسمتهای مربوط به حالت سخت درست اجرا میشن یا نه، به این حالت اعتماد کنین.
در آخر، مطمئن بشین که کد خودتون رو در مرورگرهایی که حالت سخت رو پشتیبانی میکنن و پشتیبانی نمیکنن، آزمایش کردین. اگه فقط اون رو در مرورگرهایی تست کنین که از حالت سخت پشتیبانی نمیکنن، پس به احتمال زیاد در مرورگرهایی که این کار رو انجام میدن با مشکل روبرو میشین و بالعکس. از این رو، در هنگام استفاده از حالت سختگیرانه در مرورگرها، انجام یه سری اقدامات احتیاطی، لازمه.
تغییرات در حالت سختیگرانه
حالت سخت، هم نحو و هم زمان اجرا رو تغییر و تحت تاثیر قرار میده. این تغییرات به طور کلی در دستههای زیر قرار میگیرن:
- تغییراتی که اشتباهات رو به خطا تبدیل میکنن (به عنوان خطاهای نحوی یا زمان اجرا) ،
- تغییراتی که نحوه محاسبه یه متغیر خاص برای استفاده مشخص از یک نام رو ساده میکنن،
- تغییراتی که Eval و آرگومان رو ساده میکنن،
- تغییراتی که نوشتن جاوا اسکریپت «امن» رو آسون میکنن و پیش بینی تکامل آینده ECMAScript رو تغییر میدن.
تبدیل اشتباهات به خطا
حالت strict mode در جاوا اسکریپت برخی از اشتباهاتی که قبلاً پذیرفته شده رو به خطا تغییر میده. علاوه بر این حالت سخت، ایجاد تصادفی متغیرهای جهانی رو غیرممکن میکنه. در جاوا اسکریپت معمولی وقتی متغیری به اشتباه نوشته بشه یه ویژگی جدیدی روی شی global جهانی ایجاد میشه و به کار خودش ادامه میده.
'use strict';
// Assuming a globalvariable mistypedVariable exists
mistypeVariable = 17;
// this line throws a ReferenceError due to the
// misspelling of variable
حالت سخت وظایفی رو انجام میده که در غیر اینصورت قادر به مدیریت یه استثنا نیست. به عنوان مثال، NaN یه متغیر جهانی غیرقابل نوشتنه، در حالت عادی، اختصاص کد به NaN هیچ کار خاصی انجام نمیده و توسعه دهنده هیچ بازخوردی درباره شکست دریافت نمیکنه.
'use strict';
// Assignment to a non-writable global
var undefined = 5; // throws a TypeError
var Infinity = 5; // throws a TypeError
// Assignment to a non-writable property
var obj1 = {};
Object.defineProperty(obj1, 'x', { value: 42, writable: false });
obj1.x = 9; // throws a TypeError
// Assignment to a getter-only property
var obj2 = { get x() { return 17; } };
obj2.x = 5; // throws a TypeError
// Assignment to a new property on a non-extensible object
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = 'ohai'; // throws a TypeError
حالت سخت تلاش میکنه تا ویژگیهای غیرقابل حذف رو حذف کنه (در صورتی که قبل از این تلاش هم اصلاً هیچ تأثیری نداشتن):
'use strict';
delete Object.prototype; // throws a TypeError
ساده سازی کاربردهای متغیر
حالت strict نحوه نامگذاری متغیرها رو برای تعریف متغیرهای خاص در کد ساده میکنه. خیلی از بهینه سازی های کامپایلر به قدرت گفتن ذخیره سازی متغیر X در اون مکان متکی هستن: این امر برای بهینه سازی کامل کد JavaScript خیلی مهمه. حالت سخت “with” رو ممنوع میکنه. مشکلی که با “with” وجود داره اینه که هر نامی در داخل بلوک ممکنه هم به یه خاصیت شی object منتقل شده و هم به یه متغیر در دامنه اطراف (یا حتی جهانی) ربط داشته باشه، در زمان اجرا: حالت سخت با خطای نحوی ایجاد میشه، بنابراین فرصتی برای یه نام در “with” وجود نداره که یه یه مکانی در runtime اشاره کنه:
'use strict';
var a = 0003;
with (obj) { // !!! syntax error
// If this weren't strict mode, would this be var x, or
// would it instead be obj.x? It's impossible in general
// to say without running the code, so the name can't be
// optimized.
a;
}
ساده سازی Eval و Arguments برای کار
strict mode در جاوا اسکریپت باعث ایجاد eval و آرگومانهای کمتر عجیبی میشه. البته هر دوی اونها شامل یه مقدار قابل توجهی از رفتارهای جادویی در کد عادی هستن: Eval برای افزودن یا حذف اتصال و تغییر مقادیر اتصال، محاسبه میشه و آرگومانها با ویژگیهای فهرست شده خودش، از آرگومان های نامگذاری شده مستقله.
حالت سخت گامهای بزرگی در جهت اسنفاده از Eval و Arguments به عنوان کلمات کلیدی برداشته، البته بهتره بدونین که اصلاحات کامل تا نسخه بعدی ECMAScript انجام نخواهد شد.
'use strict';
eval = 17;
arguments++;
++eval;
var obj = { set p(arguments) { } };
var eval;
try { } catch (arguments) { }
function x(eval) { }
function arguments() { }
var y = function eval() { };
var f = new Function('arguments', "'use strict'; return 17;");
در حال حاضر دیگه پشتیبانی از arguments.callee وجود نداره. در کد عادی، arguments.callee به تابع محصور کننده اشاره داره. البته این استفاده ضعیفه: به سادگی تابع محصور رو نام ببرین! علاوه بر این، arguments.callee به طور قابل توجهی از بهینه سازی مثل توابع درون خطی، جلوگیری میکنه، چون که ارائه ارجاع به تابع un-inline امکان پذیره. arguments.callee برای توابع حالت سخت یه ویژگی غیرقابل حذفه که هنگام تنظیم یا بازیابی، باعث پرتاب خطا میشه:
'use strict';
var strict = function() { return arguments.callee; };
strict(); // throws a TypeError
امنیت JavaScript
حالت سختگیرانه نوشتن JavaScript امن رو آسون میکنه. در حال حاضر یه سری از وبسایت ها روشهایی رو برای نوشتن JavaScript به کاربران ارائه میدن که توسط وب سایت به نمایندگی از سایر کاربران اجرا میشه. انعطاف پذیری جاوا اسکریپت انجام این کار رو بدون بررسیهای زیادی از runtime، غیرممکن میکنه. توابع خاص زبانی به حدی فراگیرن که انجام بررسیهایی برای runtime هزینه عملکرد قابل توجهی داره.
'use strict';
Function strict() { return this; }
console.assert(strict() === undefined);
console.assert(strict.call(2) === 2);
console.assert(strict.apply(null) === null);
console.assert(strict.call(undefined) === undefined);
console.assert(strict.bind(true)() === true);
اول از همه، مقداری که به این صورت به یه تابع در حالت سخت منتقل میشه حتماً نباید یه شی باشه. برای یه تابع طبیعی، این همیشه یه شی object است: شی ارائه شده اگه با یه مقداری از اون شی فراخوانی بشه؛ اون مقدار Boxed میشه، اگه با Boolean فراخوانی بشه، رشته یا عدد بهش داده میشه. اشیا global جهانی اگه تعریف نشده یا به صورت خنثی فراخوانی بشن (برای تعیین یه مورد خاص از تماس، اعمال یا اتصال استفاده کنین.).
Boxing اتوماتیک نه تنها هزینه عملکردی داره، بلکه افشای شی جهانی در مرورگرها هم یه خطر امنیتی به حساب میاد؛ چون که شی جهانی دسترسی به عملکردی رو فراهم میکنه که محیطهای «امن» JavaScript باید اون رو محدود کنن. بنابراین برای یه تابع حالت سخت، “this” مشخص شده در یه شی قرار داده نمیشه و در صورت عدم تعیین، “this” تعریف نمیشه.
مرور کلی بر حالت سخت JavaScript
همونطوری که گفتیم JavaScript Strict Mode ویژگی جدیدی در ECMAScript 5 است که به شما اجازه میده یه برنامه یا یه روش رو در یه زمینه عملیاتی “strict” کدگذاری کنین. این روشی برای انتخاب نوع محدود JavaScript است پس میتونیم بگیم که استفاده از حالت سخت جاوا اسکریپت خبر خوبیه چون که جاوا اسکریپت به بسیاری از اعمال «کدگذاری ضعیف» بدون ایجاد استثنا اجازه نوشته شدن میده. این امر میتونه باعث از کار افتادن صفحات، اجزا و کل برنامههای شما بشه، چرا که توسعه دهندگان از این که از نحو نامناسب یا الگوی بدی استفاده کردن، آگاه نبودن.
همچنین دونستین که حالت سخت چندین تغییر در معنای JavaScript معمولی ایجاد میکنه:
- با تغییر دادن اونها برای پرتاب خطاها، برخی خطاهای ساکت JavaScript رو از بین میبره.
- رفع خطاهایی که انجام بهینه سازی برای موتورهای JavaScript رو دشوار میکنن.
- برخی از نحوهایی رو که احتمالاً در نسخههای بعدی ECMAScript تعریف میشن، منع میکنه.
حالت سختگیرانه در JavaScript اجازه نداره موارد زیر رو دنبال کنه:
- استفاده از متغیرهای تعریف نشده
- استفاده از کلمات کلیدی رزرو شده به عنوان نام متغیر یا تابع
- ویژگیهای تکراری یک شی
- کپی کردن پارامترهای تابع
- اختصاص دادن مقادیر، تنها به ویژگیهای خواندنی
- اصلاح آرگومان ها
- حرفهای عددی هشتتایی
- عبارت “with”
- تابع eval برای ایجاد یه متغیر
پس در آخر یاد گرفتیم که این حالت به ما کمک میکنه تا کد رو ایمنتر و آسونتر کنیم. سادگی در استفاده از متغیرها به رمزگذاران مزایای جلوگیری از خطاهای نحوی مختلفی رو میده. همچنین میتونین از strict mode در جاوا اسکریپت هم در کل اسکریپت و هم در توابع جداگانه استفاده کنین و تغییرات زیادی رو در کار خودتون مشاهده کنین.
امیدواریم از این مقاله لذت برده باشین، نظرات و سوالات خودتون رو از طریق کامنتها با ما به اشتراک بذارین.