Strict Mode in Javascript
Tags: javascript, strictmode, programming, beginners
Published: 2022-04-25 10:20:59

ECMAScript 5 da joriy qilingan JavaScript'ning qat'iy rejimi(strict mode) JavaScript'ning cheklangan variantiga qo'shilish va shu bilan odatiy rejimdan voz kechish usulidir. Qat'iy rejim shunchaki kichik to'plam emas: u oddiy koddan farqli semantikaga ega. Qattiq rejimni qo'llab-quvvatlamaydigan brauzerlar qat'iy rejim kodini boshqa brauzerlardan boshqacharoq usulda ishga tushiradi, shuning uchun qat'iy rejimning tegishli jihatlarini brauzer qo'llab-quvvatlashini tekshirmasdan qat'iy rejimga tayanmang.

Qat'iy rejim oddiy JavaScript semantikasiga bir nechta o'zgarishlar kiritadi:

1. JavaScript-ning ba'zi bilinmas xatolarini xatolarga o'zgartirish kiritish orqali yo'qotadi.

2. JavaScript uchun optimallashtirishni qiyinlashtiradigan xatolarni tuzatadi: qat'iy rejim kodini ba'zan qat'iy rejim bo'lmagan bir xil koddan tezroq ishlash uchun ham ishlatiladi.

3. ECMAScript ning kelajakdagi versiyalarida aniqlanishi mumkin bo'lgan ba'zi sintaksislarni taqiqlaydi.

## Qat'iy rejimni chaqirish.

Qat'iy rejim butun bir skriptlar yoki alohida funksiyalar uchun amal qiladi. Bu **{}** ichiga olingan blok _statement_'larga taalluqli emas; uni bunday kontekstlarga qo'llashga urinish natija bermaydi. `eval` code, `function` code, `event handler` attributlar, `setTimeout()` ga uzatilgan tekstlar va tegishli funktsiyalar butun skriptlardir va ulardagi qat'iy rejimni chaqirish kutilganidek ishlaydi.

### Skriptlar uchun qat'iy rejim.

Butun bir skript uchun qat'iy rejimni ishga tushirish uchun, skriptning eng birinchi qatoriga `"use strict"` yoki `'use strict'` iborasini yozing.

```js
// butun bir skript qat'iy rejimda bo'lgan holat
'use strict';
var v = "Salom, men qat'iy rejimdagi skriptman!";

```

### Funksiyalar uchun qat'iy rejim.

Xuddi shunday, Funksiyalar uchun qat'iy rejimni ishga tushirish uchun, funksiya tanasining eng birinchi qatoriga `"use strict"` yoki `'use strict'` iborasini yozing.

```js
function strict() {
  // Funksiya darajasidagi qat'iy rejim sintaksisi
  'use strict';
  function nested() { return "Men ham qat'iy rejimdaman!"; }
  return "Salom!  Men qat'iy rejimdagi funksiyaman!  " + nested();
}
function notStrict() { return "Men esa qat'iy rejimda emasman"; }

```

ES2015 dan boshlab qat'iy rejimda bloklar ichidagi funksiyalar ushbu blokda qamrab olinadi. ES2015 ga qadar blok darajasidagi funksiyalar qat'iy rejimda taqiqlangan edi.

### Modullar uchun qat'iy rejim.

ECMAScript 2015 JavaScript modullarini va shu bilan birga qat'iy rejimga kirishning uchinchi usulini ham taqdim etdi. JavaScript modullarining butun tarkibi avtomatik ravishda qat'iy rejimda bo'ladi, uni boshlash uchun hech qanday maxsus kalit so'z kerak emas.

```js
function strict() {
    // bu modul bo'lganligi tufayli men avtomatik qat'iy rejimdaman
}
export default strict;

```

### Classlar uchun qat'iy rejim.

ECMAScript classlarining barcha qismlari qat'iy rejim kodi bo'lib, class deklaratsiyasi va class ifodalarini o'z ichiga oladi va shu bilan birga class tanasining barcha qismlarini ham o'z ichiga oladi.

## Qat'iy Rejimda Bo'ladigan O'zgarishlar.

Qat'iy rejim ham sintaksis, ham ishga tushirish usullarini o'zgartiradi. O'zgarishlar odatda quyidagi toifalarga bo'linadi: adashishni xatolarga aylantiruvchi o'zgarishlar (sintaksis xatolari yoki runtime), `eval` va `argument` larni soddalashtiruvchi o'zgarishlar, "_xavfsiz_" JavaScript kod yozishni osonlashtiruvchi va kelajakdagi ECMAScript evolyutsiyasini bashorat qilishi mumkin bo'lgan o'zgarishlar.

### Adashishni Xatoga aylantirish.

Qat'iy rejim ilgari odatdagidek qabul qilingan ba'zi adashishlarni xatolarga o'zgartiradi. JavaScript yangi o'rganuvchilar uchun juda oson va ba'zida u semantikada xato bo'lishi kerak bo'lgan xato bo'lmagan operatsiyalarni beradi. Ba'zida bu darhol muammoni hal qiladi, lekin ba'zida bu yanada yomonroq muammolarni keltirib chiqaradi. Qat'iy rejim bu adashishlarni xato deb hisoblaydi, ular topiladi va tezda tuzatiladi.

Qattiq rejim ilgari qabul qilingan ba'zi xatolarni xatolarga o'zgartiradi. JavaScript yangi boshlanuvchilar uchun oson bo'lishi uchun yaratilgan va ba'zida u semantikada xato bo'lmagan xatolar bo'lishi kerak bo'lgan operatsiyalarni beradi. Ba'zida bu darhol muammoni hal qiladi, lekin ba'zida bu kelajakda yanada yomonroq muammolarni keltirib chiqaradi. Qattiq rejim bu xatolarni xato deb hisoblaydi, shunda ular topiladi va tezda tuzatiladi.

Birinchidan, qat'iy rejim tasodifiy global o'zgaruvchilarni yaratish imkonsiz. Oddiy JavaScript'da, o'zgaruvchini noto'g'ri yozish global obyektda yangi property'ni yaratadi va "ishlashda" davom etadi. Qat'iy rejimda esa global o'zgaruvchini tasodifan yaratish xatoga olib keladi:

```js
'use strict';
                       // mistypeVariable deb nomlanuvchi global o'zgaruvchi yo'q deb tasavvur qiling
mistypeVariable = 17;  // Bu qator ReferenceError qaytaradi chunki bu nomdagi o'zgaruvchi mavjud emas.

```
`NaN` yozib bo'lmaydigan global o'zgaruvchidir. Oddiy kodda `NaN` ga qiymat berish hech narsani anglatmaydi; dasturchi hech qanday xato qabul qilmaydi. Qat'iy rejimda `NaN` ga qiymat berish istisno(exception)ni keltirib chiqaradi. Oddiy kodda shunchaki e'tibordan chetda qoladigan qiymat berishlar (yozib bo'lmaydigan global yoki property'ga qiymat berish, faqat qabul qiluvchi(getter-only) property'ga qiymat berish, kengaytirilmaydigan obyektda yangi property qo'shish) qat'iy rejimda xato qaytaradi:

```js
'use strict';

// yozib bo'lmaydigan globalga qiymat berish
var undefined = 5; // TypeError qaytaradi
var Infinity = 5; // TypeError qaytaradi

// yozib bo'lmaydigan property'ga qiymat berish
var obj1 = {};
Object.defineProperty(obj1, 'x', { value: 42, writable: false });
obj1.x = 9; // TypeError qaytaradi

// getter-only property'ga qiymat berish
var obj2 = { get x() { return 17; } };
obj2.x = 5; // TypeError qaytaradi

// kengaytirib bo'lmaydigan obyektga yangi qiymat qo'shish
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = 'ohai'; // TypeError qaytaradi

```

Qat'iy rejim o'chirib bo'lmaydigan property'larni o'chirishga urinishlar qiladi :

```js
'use strict';
delete Object.prototype; // TypeError qaytaradi

```
Qat'iy rejim funksiya parametr nomlarining yagona bo'lishini talab qiladi. Oddiy kodda oxirgi takrorlangan argument avvalgi bir xil nomdagi argumentlarni yashirib qo'yadi. Avvalgi argumentlarga arguments[i]  orqali murojjat qilish mumkin, shuning uchun aytish mumkinki ular to'liq yo'q bo'lib ketmagan. Shunga qaramay, bu yashirish kichik bo'lsada ma'noga ega va xohlamagan holda amalga oshirilgan bo'lishi mumkin(masalan, u xato yozishni yashirib qo'yishi mumkin), shuning uchun qat'iy rejimda argument nomlarining takrorlanishi `syntax error` hisoblanadi:

```js
function sum(a, a, c) { // !!! syntax error
  'use strict';
  return a + a + c; // xato!!!
}
```

ECMAScript5'da qat'iy rejim 0-prefiksli octal(sakkizlik) literal yoki octal sequense(sakkiztalik ketma-ketlik) taqiqlaydi. Qat'iy rejimdan tashqarida `0` bilan boshlanadigan raqam, masalan, `0644`, agar barcha raqamlar 8 dan kichik boʻlsa, sakkizlik son (`0644 === 420`) sifatida talqin etiladi. Sakkizlik ketma-ketligi, masalan, "%" ga teng bo'lgan “\45”, sakkizta kengaytirilgan ASCII belgilar kodlarining raqamlari bilan belgilarni ko'rsatish uchun ishlatilishi mumkin. Qat'iy rejimda bu `syntax error`. ECMAScript 2015 da sakkizlik literallar songa "`0o`" prefiks qo'yish orqali bajariladi; misol uchun:

```js
var a = 0o10; // ES2015: Octal
```

Yangi o'rganuvchilar ba'zan nol prefiksining semantik ma'nosi yo'qligiga ishonishadi, shuning uchun ular uni alignment moslamasi sifatida ishlatishlari mumkin - lekin bu raqamning ma'nosini o'zgartiradi! Sakkizlik uchun boshidagi nol sintaksisi kamdan-kam foydali bo'lib va va ba'zan xato tarzda ishlatilishi mumkin, shuning uchun qattiq rejim uni `syntax error`'ga aylantirilgan:

```js
'use strict';
var sum = 015 + // !!! syntax error
          197 +
          142;

var sumWithOctal = 0o10 + 8;
console.log(sumWithOctal); // 16
```

ECMAScript 2015 da qat'iy rejim `primitive` qiymatlarga property o'rnatishni taqiqlaydi. Qattiq rejimsiz property o'rnatish e'tiborga olinmaydi (no-op), qattiq rejimda esa `TypeError`'ga olib keladi.

```js
(function() {
'use strict';

false.true = '';         // TypeError
(14).sailing = 'home';   // TypeError
'with'.you = 'far away'; // TypeError

})();
```

ECMAScript 5 qat'iy rejim kodida property nomlarini takrorlanishi `SyntaxError` deb hisoblangan. `computed property name` kiritilishi bilan `runtime`'da nomlar takrorlanishi mumkin bo'ldi. ECMAScript 2015 bu cheklovni olib tashladi.

```js
'use strict';
var o = { p: 1, p: 2 }; // ECMAScript 2015 ko'ra syntax error
```

### `eval` va `argument`'larni soddalashtirish.

Qat'iy rejim `arguments` va `eval`'larning sehrini kamaytiradi. Ikkalasi ham oddiy kodda katta miqdordagi sehrli xatti-harakatni o'z ichiga oladi: bog'lanishlarni qo'shish yoki olib tashlash va bog'lanish qiymatlarini o'zgartirish uchun `eval`. Qat'iy rejim `eval` va `arguments` kalit so'zlar sifatida ko'rib chiqishni o;zragtirmoqda, ammo to'liq tuzatishlar ECMAScript ning kelajakdagi varsiyalarida amalga oshirilishi kutilyapti.

Birinchidan, `eval` va `argument` nomlarini til sintaksisida bog‘lab yoki qiymat berib bo‘lmaydi. Buni amalga oshirishga urinishlarning barchasi sintaktik xatolardir:

```js
'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;");
```

Ikkinchidan, qat'iy rejim kodi unda yaratilgan `argumentlar` obyektlarining xususiyatlariga nom bermaydi. Birinchi argumenti `arg` bo'lgan funksiya ichidagi oddiy kodda `arg`  `arguments[0]`ni ham o'rnatadi va aksincha (argumentlar taqdim etilmagan yoki argumentlar[0] o'chirilgan bo'lsa). `arguments` qat'iy rejim funktsiyalari uchun obyektlar funktsiya chaqirilganda asl argumentlarni saqlaydi. `arguments[i]` tegishli nomli argumentning qiymatini kuzatmaydi va nomli argument tegishli `arguments[i]` qiymatini kuzatmaydi.

```js
function f(a) {
  'use strict';
  a = 42;
  return [a, arguments[0]];
}
var pair = f(17);
console.assert(pair[0] === 42);
console.assert(pair[1] === 17);
```

Uchinchidan, `arguments.callee` endi qo'llab-quvvatlanmaydi. Oddiy kodda `arguments.callee` o'zini o'rab turgan funktsiyasiga ishora qiladi. Ushbu foydalanish holati xavfsiz emas! Bundan tashqari, `arguments.callee` inlining funktsiyalari kabi optimallashtirishga sezilarli darajada to'sqinlik qiladi, chunki agar `arguments.callee` ga kirilgan bo'lsa, inlined funksiyasiga havolani taqdim etish imkoniyati yaratilishi kerak. `arguments.callee` qat'iy rejim funktsiyalari uchun o'chirib bo'lmaydigan xususiyat bo'lib, qiymat berilganda yoki olinganida xatolik keltirib chiqaradi:

```js
'use strict';
var f = function() { return arguments.callee; };
f(); // TypeError qaytaradi
```

### Xavfsiz Javascript.

Qat'iy rejim JavaScriptni "xavfsiz" yozishni osonlashtiradi. Ba'zi veb-saytlar endi foydalanuvchilarga JavaScript yozishning turli usullarini taqdim etadi. Brauzerlardagi JavaScript foydalanuvchining shaxsiy ma'lumotlariga kirishi mumkin, shuning uchun bunday JavaScript taqiqlangan funksiyalarga kirishni tsenzura qilish uchun ishga tushirishdan oldin qisman o'zgartirilishi kerak. JavaScriptning moslashuvchanligi sababli buni `runtime` tekshiruvlarisiz amalga oshirish imkonsiz. Ba'zi til funktsiyalari shu qadar keng tarqalganki, `runtime` tekshirishni amalga oshirish katta xarajatlarini talab qiladi. Bir nechta qat'iy rejim o'zgarishlari, shuningdek, foydalanuvchi tomonidan taqdim etilgan JavaScriptning qat'iy rejim kodi bo'lishini va uni ma'lum bir tarzda ishga tushirishni talab qilish, bu `runtime` tekshirishga bo'lgan ehtiyojni sezilarli darajada kamaytiradi.

Birinchidan, qat'iy rejimdagi funktsiyaga berilgan `this` qiymati obyekt bo'lishga majburlanmaydi. Oddiy funktsiya uchun `this` har doim obyekt hisoblanadi: yoki taqdim etilgan obyekt 
`this` obyekti bilan chaqirilgan bo'lsa; qiymat, agar `boolean`, `string` yoki `number` bilan chaqirilgan bo'lsa; yoki global obyekt, agar bu `undefined` yoki `null` bilan chaqirilsa. Avtomatik box nafaqat  xarajatni, balki global obyektni brauzerlarda ko'rsatish xavfsizlik uchun xavf tug'diradi, chunki global obyekt "xavfsiz" JavaScript muhiti oldini olishi kerak bo'lgan funksiyalarga kirishni ta'minlaydi. Shunday qilib, qat'iy rejim funktsiyasi uchun belgilangan `this` obyektga kiritilmaydi va agar `aniqlanmagan` bo'lsa, bu `undefined` bo'ladi:

```js
'use strict';
function fun() { return this; }
console.assert(fun() === undefined);
console.assert(fun.call(2) === 2);
console.assert(fun.apply(null) === null);
console.assert(fun.call(undefined) === undefined);
console.assert(fun.bind(true)() === true);
```

Ikkinchidan, qat'iy rejimda ECMAScript kengaytmalari orqali JavaScript stekini “yuritish” endi mumkin emas. Bu kengaytmalarga ega oddiy kodda `fun` funksiya chaqirishning o‘rtasida bo‘lsa, `fun.caller` oxirgi marta `fun` deb atalgan funksiya, `fun.arguments` esa `fun`'ni chaqirish uchun argumentdir. Ikkala kengaytma ham "xavfsiz" JavaScript uchun muammoli, chunki ular "xavfsiz" kodga "privileged" funktsiyalarga va ularning (potentsial himoyalanmagan) argumentlariga kirishga imkon beradi. Agar `fun` qatʼiy rejimda boʻlsa, `fun.caller` va `fun.arguments` ham oʻchirib boʻlmaydigan xususiyatlar boʻlib, xato qaytaradi:

```js
function restricted() {
  'use strict';
  restricted.caller;    // TypeError qaytaradi
  restricted.arguments; // TypeError qaytaradi
}
function privilegedInvoker() {
  return restricted();
}
privilegedInvoker();
```

## Brauzerlarda qat'iy rejim.

Taxminan 2012 yildan beri asosiy brauzerlar qat'iy rejimni to'liq joriy qilgan, jumladan IE 10-versiyasi, Firefox 4-versiyasidan beri, Chrome 13-versiyasidan beri va hokazo. Agar siz hali ham qat'iy rejim qo'llab-quvvatlanishidan oldingi juda eski JS environtment ishlatsangiz, JS engine'ga mos keladigan qat'iy bo'lmagan rejimda ishlayotganda uning kutilgan behavior'i buzilmasligini tekshirish uchun qat'iy rejim kodini e'lon qiladigan har qanday kodingizni sinab ko'ring.

Brauzerlarda qat'iy rejim qanday ishlashini hisobga olish kerak bo'lgan ba'zi nuanslar mavjud.

Qat'iy rejim skript yoki funksiyaning yuqori darajasida bo'lmagan `function statement`'larni oldini oladi. Brauzerlarda oddiy rejimda `function statement`ga  hamma joyda ruxsat beriladi. Bu ES5 (yoki hatto ES3) ning bir qismi emas! Bu turli xil brauzerlarda mos kelmaydigan semantikaga ega kengaytma. E'tibor bering, ES2015 da yuqori darajadan tashqarida bo'lgan `function statement`'larga ruxsat berilgan.

Masalan, ushbu blok-darajali funksiya deklaratsiyasiga spetsifikatsiya matni tomonidan qat'iy rejimda ruxsat berilmasligi kerak:

```js
if (true) {
  function f() { } // !!! syntax error
  f();
}

for (var i = 0; i < 5; i++) {
  function f2() { } // !!! syntax error
  f2();
}

function baz() { // kosher
  function eit() { } // also kosher
}
```


Maqola vanihoyat o'z nihoyasiga yetdi, Sabr bilan ushbu qatorgacha o'riganingiz uchun rahmat. Allah ilmingizni ziyoda qilsin.