Apa itu "mode ketat" dan bagaimana cara menggunakannya? Gunakan javascript yang ketat apa itu, kesalahan skrip java Apa yang terjadi jika browser saya tidak mendukung Mode Ketat




Mode ketat (direktif "gunakan ketat") adalah hal yang sangat bagus dalam JavaScript dan sangat mudah untuk memulainya!

Bagaimana menerapkannya

// file.js "gunakan ketat" fungsi doStuff(){ // mode ketat diaktifkan }

Pada contoh di atas, mode ketat diterapkan di seluruh kode di file.js .

Jika Anda hanya ingin memasukkannya ke dalam fungsi, gunakan contoh berikut:

// file.js fungsi a()("gunakan ketat" ; // mode ketat hanya diaktifkan untuk kode di dalam fungsi fungsi nestedFunction(){ // dan juga akan diterapkan di dalam fungsi bersarang } }

Keuntungan

Gandakan kunci dalam suatu objek

var zombie = ( mata Kiri: 0 , mata Kanan: 1 , // ... banyak kunci ... mata Kiri: 1)

Akibatnya kita akan mendapatkan error, karena key eyeLeft muncul dua kali. Dalam hal ini, mode ketat akan menyelamatkan Anda dari duplikasi kunci di objek.

Variabel tanpa var

bidang = 5 ;

Anda mungkin sudah tahu masalah apa yang bisa muncul jika Anda lupa menambahkan kata kunci var dalam deklarasi variabel. Jika tidak, ketahuilah bahwa sangat sulit untuk men-debug kode tersebut nanti, karena variabel seperti itu akan dideklarasikan dalam konteks global dan dapat diubah oleh bagian lain dari program.

Bayangkan saja sebuah variabel yang saya nyatakan secara global. Ini dapat mengacaukan semua loop bersarang dalam aplikasi.

Duplikat Argumen

{}

Harap perhatikan bahwa argumen fromWhom ditulis dua kali, untuk kasus ini, kesalahan juga akan ditampilkan dalam mode ketat

Apa yang penuh dengan kesalahan seperti itu:

menjalankan fungsi (fromWhom, fromWhom )(alert(fromWhom)) run(1 , 2 ); // waspada: 2

Memperbaiki argumen di dalam suatu fungsi

var jalankan = fungsi (dari Siapa)( argumen = "alien" ; alert(fromWhom); ) run("zombie" ); // peringatan: "alien";

Jika menggunakan mode ketat:

var jalankan = fungsi (dari Siapa)( "gunakan ketat" ; argumen = "alien" ; alert(fromWhom); ) run("zombie" ); // waspada: "zombie";

Betapa tidak jelas bahwa mengubah argumen (arguments = "alien") mengubah argumen bernama dari Whom ? Arahan "gunakan ketat" akan menyelamatkan Anda dari kesulitan ini.

WoollyMittens, pengguna reddit disarankan dalam komentar:

Bersamaan dengan mode ketat, Anda dapat menginstal "linter" (http://www.jshint.com/) untuk menghindari kesalahan bodoh bahkan sebelum menjalankan kode. Untuk sebagian besar editor, ada plugin yang sesuai. Anda dapat menganggapnya sebagai garis berlekuk-lekuk merah yang menggarisbawahi kesalahan tata bahasa Anda saat menulis email, tetapi terkait dengan kodenya.

Segera saya akan menjelaskan bagaimana Anda dapat mengotomatiskan semua ini menggunakan grunt.

loz220 , pengguna reddit V

JavaScript - Mode ketat

Rezim yang ketat

Terkadang Anda akan melihat mode default non-standar dipanggil "modus ceroboh". Ini bukan istilah resmi, tapi ingatlah itu, untuk berjaga-jaga.

(function() ( "use strict"; false.true = ""; // TypeError (14).sailing = "home"; // TypeError "with".you = "jauh"; // TypeError ))( );

Menyederhanakan penggunaan variabel

Mode ketat memudahkan pencocokan nama variabel dengan definisi variabel tertentu dalam kode Anda. Banyak pengoptimal kompiler mengandalkan kemampuan untuk mengatakan bahwa variabel X disimpan di ini lokasi: Ini sangat penting untuk mengoptimalkan kode JavaScript Anda sepenuhnya. JavaScript terkadang melakukan pemetaan definisi nama-ke-variabel dasar ini dalam kode yang tidak dapat dilakukan sebelum eksekusi. Mode ketat menghapus sebagian besar kasus di mana hal ini terjadi, sehingga kompiler dapat mengoptimalkan kode mode ketat dengan lebih baik.

Pertama, mode ketat dilarang. Masalahnya adalah bahwa nama apa pun di dalam blok dapat mewakili properti objek yang diteruskan ke sana, atau variabel lingkungan (atau bahkan global) saat runtime: tidak ada cara untuk mengetahui ini sebelumnya. Mode ketat dijalankan dengan kesalahan sintaksis, jadi tidak ada kemungkinan nama dalam a yang merujuk ke lokasi yang tidak diketahui saat runtime:

"gunakan ketat"; var x = 17; dengan (obj) ( // !!! kesalahan sintaks // Jika ini bukan mode ketat, apakah ini var x, atau // sebaliknya obj.x? Secara umum tidak mungkin // untuk mengatakan tanpa menjalankan kode, sehingga namanya tidak dapat // dioptimalkan.x; )

Alternatif sederhana untuk menugaskan objek ke variabel nama pendek, lalu mengakses properti yang sesuai untuk variabel itu, siap diganti dengan .

Kedua, . Dalam kode normal, eval("var x;") memperkenalkan variabel x ke dalam fungsi sekitarnya atau lingkup global. Ini berarti bahwa, secara umum, dalam fungsi yang berisi panggilan eval, setiap nama variabel non-argumen atau lokal harus dipetakan ke definisi tertentu pada waktu proses (karena eval tersebut dapat memperkenalkan variabel baru yang akan menyembunyikan variabel luar). Dalam mode ketat, eval hanya membuat variabel untuk kode yang sedang dievaluasi, jadi eval tidak berpengaruh pada apakah suatu nama merujuk ke variabel eksternal atau beberapa variabel lokal:

Var x = 17; var evalX = eval(""gunakan ketat"; var x = 42; x;"); console.assert(x === 17); console.assert(evalX === 42);

Jika fungsi eval dipanggil dengan ekspresi bentuk eval(...) dalam kode mode ketat, kode tersebut akan dievaluasi sebagai kode mode ketat. Kode dapat secara eksplisit merujuk ke mode ketat, tetapi tidak harus begitu.

Fungsi strict1(str) ( "gunakan ketat"; return eval(str); // str akan diperlakukan sebagai kode mode ketat ) function strict2(f, str) ( "gunakan ketat"; kembalikan f(str); // tidak eval(...): str ketat jika dan hanya // jika memanggil mode ketat ) function nonstrict(str) ( return eval(str); // str ketat jika dan hanya // jika memanggil mode ketat ) strict1 (""Kode mode ketat!""); strict1(""gunakan ketat"; "Kode mode ketat!""); strict2(eval, ""Kode tidak ketat.""); strict2(eval, ""gunakan ketat"; "Kode mode ketat!""); nonstrict(""Kode tidak ketat.""); nonstrict(""gunakan ketat"; "Kode mode ketat!"");

Dengan demikian, nama dalam kode strict eval berperilaku sama dengan nama dalam mode ketat, yang tidak dievaluasi sebagai hasil dari eval .

Ketiga, mode ketat melarang penghapusan nama sederhana. hapus nama dalam mode ketat adalah kesalahan sintaksis:

"gunakan ketat"; varx; hapus x; // !!! kesalahan sintaks eval("var y; hapus y;"); // !!! kesalahan sintaks

Menyederhanakan eval dan argumen

Mode ketat membuat argumen dan eval tidak terlalu ajaib. Keduanya melibatkan sejumlah besar perilaku magis dalam kode normal: eval untuk menambah atau menghapus binding dan mengubah nilai binding, dan argumen menggunakan properti aliasing terindeks dengan nama argumen. Mode ketat membuat langkah besar untuk menangani eval dan argumen sebagai kata kunci, meskipun perbaikan penuh tidak akan muncul hingga rilis ECMAScript di masa mendatang.

Pertama, nama eval dan argumen tidak dapat diikat atau ditetapkan dalam sintaks bahasa. Semua upaya ini adalah kesalahan sintaksis:

"gunakan ketat"; nilai = 17; argumen++; ++nilai; var obj = ( atur p(argumen) ( ) ); vareval; coba ( ) tangkap (argumen) ( ) fungsi x(eval) ( ) argumen fungsi() ( ) var y = fungsi eval() ( ); var f = new Fungsi("argumen", ""gunakan ketat"; return 17;");

Kedua, kode mode ketat tidak mendukung properti objek argumen yang dibuat di dalamnya. Dalam kode normal, di dalam fungsi yang argumen pertamanya adalah arg , parameter arg juga menetapkan argumen, dan sebaliknya (jika tidak ada argumen yang diberikan atau argumen dihapus). objek argumen untuk fungsi mode ketat menyimpan argumen asli saat fungsi dipanggil. argumen[i] tidak melacak nilai argumen bernama yang sesuai, juga argumen bernama tidak melacak nilai dalam argumen[i] yang sesuai.

Fungsi f(a) ( "gunakan ketat"; a = 42; return ; ) var pair = f(17); console.assert(pasangan === 42); console.assert(pasangan === 17);

Ketiga, argument.callee tidak lagi didukung. Dalam argumen normal.callee mengacu pada fungsi penutupan. Kasus penggunaan ini lemah: panggil saja fungsi sertakan! Selain itu, argument.callee membuat pengoptimalan, seperti fungsi inline, jauh lebih sulit, karena Anda harus memberikan referensi ke fungsi non-inline jika access.callee merujuknya. argument.callee untuk fungsi mode ketat adalah properti tidak terpakai yang dihasilkan saat disetel atau diambil:

"gunakan ketat"; var f = function() ( kembalikan argumen.callee; ); F(); // melempar TypeError

JavaScript "Mempertahankan".

Mode ketat memudahkan untuk menulis JavaScript "aman". Beberapa situs web sekarang mengizinkan pengguna untuk menulis JavaScript yang akan dijalankan oleh situs web tersebut atas nama pengguna lain. JavaScript di browser dapat mengakses informasi pribadi pengguna, jadi JavaScript tersebut harus dikonversi sebagian sebelum dapat dijalankan untuk menyensor akses ke fungsionalitas yang dilarang. Fleksibilitas JavaScript membuat hal ini tidak mungkin dilakukan tanpa banyak pemeriksaan runtime. Beberapa fitur bahasa sangat umum sehingga menjalankan pemeriksaan runtime memerlukan biaya yang signifikan. Beberapa pengaturan mode ketat, serta persyaratan bahwa JavaScript khusus menjadi kode mode ketat dan dipanggil dengan cara tertentu, sangat mengurangi kebutuhan akan pemeriksaan runtime ini.

Pertama, nilai yang diteruskan sebagai fungsi ke fungsi dalam mode ketat tidak dipaksa menjadi objek (alias "kotak"). Untuk fungsi normal, ini selalu berupa objek: baik objek yang disediakan jika dipanggil dengan nilai objek; nilai, kotak, jika dipanggil dengan boolean, string, atau nomor ini; atau objek global jika dipanggil dengan undefined atau null this . (Gunakan call , apply , atau bind untuk menentukan this spesifik .) Tidak hanya auto-boxing untuk kinerja, tetapi tampilan objek global di browser merupakan risiko keamanan, karena objek global menyediakan akses ke fitur yang lingkungan JavaScript " melindungi" harus membatasi. Jadi, untuk fungsi mode ketat, yang ditentukan ini tidak dimasukkan ke dalam objek, dan jika tidak ditentukan, ini tidak akan ditentukan:

"gunakan ketat"; 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);

Artinya, antara lain, di browser tidak mungkin lagi merujuk ke objek jendela melalui ini di dalam fungsi mode ketat.

Kedua, dalam mode ketat, tidak mungkin lagi "berjalan" di atas kaca JavaScript melalui ekstensi umum di ECMAScript. Dalam kode normal dengan ekstensi ini, saat fungsi fun berada di tengah fun.caller , fun.caller adalah fungsi yang baru saja dipanggil fun , dan fun.arguments adalah argumen untuk panggilan fun . Kedua ekstensi bermasalah untuk JavaScript "aman" karena memungkinkan kode "aman" untuk mengakses fungsi "istimewa" dan argumennya (yang berpotensi tidak aman). Jika kesenangan dalam mode ketat, baik fun.caller dan fun.arguments bukanlah properti yang dilemparkan saat disetel atau diambil:

Fungsi dibatasi() ( "gunakan ketat"; pemanggil terbatas; // melempar Argumen TypeError terbatas; // melempar TypeError ) fungsi privilegedInvoker() ( kembali dibatasi(); ) privilegedInvoker();

Ketiga, argumen untuk fungsi mode ketat tidak lagi menyediakan akses ke variabel pemanggilan fungsi yang sesuai. Dalam beberapa implementasi ECMAScript yang lebih lama, argument.caller adalah objek yang propertinya mengubah variabel dalam fungsi tersebut. Ini adalah risiko keamanan karena melanggar kemampuan untuk menyembunyikan nilai istimewa melalui abstraksi fungsi; itu juga menghilangkan sebagian besar pengoptimalan. Karena alasan ini, browser terbaru tidak menerapkannya. Namun, karena fungsionalitas historisnya, argument.caller untuk fungsi mode ketat juga merupakan properti non-true yang dibuat saat disetel atau diambil:

"gunakan ketat"; function fun(a, b) ( "use strict"; var v = 12; return argument.caller; // melempar TypeError ) fun(1, 2); // tidak mengekspos v (atau a atau b)

Membuka jalan bagi versi ECMAScript yang akan datang

Versi ECMAScript yang akan datang kemungkinan akan memperkenalkan sintaks baru, dan mode ketat di ECMAScript 5 menerapkan beberapa batasan untuk memudahkan transisi. Akan lebih mudah untuk melakukan beberapa perubahan jika dasar-dasar perubahan tersebut dinonaktifkan dalam mode ketat.

Pertama, dalam mode ketat, daftar singkat pengidentifikasi menjadi kata kunci yang dipesan. Kata-kata ini adalah implements , interface , let , package , private , protected , public , static , dan yield . Dalam mode ketat, Anda tidak dapat memberi nama atau menggunakan variabel atau argumen dengan nama ini.

Paket fungsi(dilindungi) ( // !!! "gunakan ketat"; implementasi var; // !!! antarmuka: // !!! sementara (benar) ( istirahat antarmuka; // !!! ) fungsi pribadi( ) ( ) // !!! ) fungsi menyenangkan(statis) ( "gunakan ketat"; ) // !!!

Dua peringatan khusus Mozilla: Pertama, jika kode Anda 1.8 atau lebih (mis. dalam kode chrome atau saat menggunakan hak, tidak akan dapat menggunakan let / yield sebagai pengidentifikasi. Kedua, sementara ES5 menyimpan tanpa syarat kata-kata class , enum , export , extends , import , dan super sebelum Firefox 5 Mozilla mencadangkannya hanya dalam mode ketat.

Kedua, . Dalam mode normal, di browser, pernyataan fungsi diizinkan "di mana saja". Itu bukan bagian dari ES5 (atau bahkan ES3)! Ini adalah ekstensi dengan semantik yang tidak konsisten di seluruh browser. Perhatikan bahwa di ES2015, pernyataan fungsi diizinkan di luar level teratas.

"gunakan ketat"; if (benar) ( ​​fungsi f() ( ) // !!! kesalahan sintaks f(); ) untuk (var i = 0; i< 5; i++) { function f2() { } // !!! syntax error f2(); } function baz() { // kosher function eit() { } // also kosher }

Larangan ini tidak ketat karena deklarasi fungsi tersebut merupakan perpanjangan dari ES5 yang mendasarinya. Tapi ini adalah rekomendasi dari komite ECMAScript, dan browser mengimplementasikannya.

Mode ketat di browser

Browser utama sekarang menerapkan mode ketat. Namun, jangan terlalu bergantung padanya, karena masih banyak versi browser yang digunakan di alam liar yang memiliki dukungan sebagian atau tidak mendukung mode ketat (mis. Internet Explorer di bawah versi 10!). Mode ketat mengubah semantik. Mengandalkan perubahan ini akan menghasilkan bug dan bug di browser yang tidak menerapkan mode ketat. Berhati-hatilah saat menggunakan mode ketat, dan pertahankan kepercayaan dalam mode ketat dengan uji fungsional yang memeriksa apakah bagian yang sesuai dari mode ketat diterapkan. Akhirnya, pastikan uji kode Anda di browser yang mendukung dan tidak mendukung mode ketat. Jika Anda hanya menguji di browser yang tidak mendukung mode ketat, kemungkinan besar Anda akan mengalami masalah dengan browser yang mendukungnya, dan sebaliknya.

Modus ketat(diterjemahkan dari bahasa Inggris - mode ketat) adalah model untuk mem-parsing dan mengeksekusi kode JavaScript, yang menggunakan pemeriksaan kode yang lebih ketat untuk kesalahan dan menghasilkan kesalahan selama tindakan tidak aman.

Aktifkan Mode Ketat

Untuk mengaktifkan mode ketat untuk seluruh skrip, tambahkan perintah berikut ke bagian atas skrip:

"gunakan ketat";

Meskipun terlihat seperti string, sebenarnya ini adalah direktif yang menempatkan JavaScript dalam mode ketat.

Mode ketat juga dapat diaktifkan untuk satu fungsi dengan menambahkan arahan ini ke awal badan fungsi:

Fungsi foo() ( "gunakan ketat"; )

Arahan "use strict" hanya dapat ditentukan di awal skrip atau di awal fungsi. Ini tidak berarti harus ada di baris pertama, tetapi harus dicantumkan sebelum instruksi lainnya. Jika arahan "gunakan ketat" ditentukan bukan di awal, tetapi di tempat lain, itu tidak akan berfungsi:

"gunakan ketat"; // Lokasi yang benar a = 5; waspada(a); b = 1; waspada(b); a = 5; waspada(a); "gunakan ketat"; // Salah lokasi. Arahan tidak akan berfungsi b = 1; waspada(b);

Menjalankan JavaScript dalam Mode Ketat

  • Semua variabel harus dideklarasikan sebelum dapat digunakan. Mencoba menggunakan variabel sebelum deklarasi melontarkan pengecualian.
  • Terjadi kesalahan saat mencoba menetapkan nilai ke variabel yang tidak dideklarasikan. Namun, secara eksplisit membuat properti dari objek global dan memberikan nilai padanya tidak menyebabkan kesalahan: window.num = 10
  • Kata-kata berikut tidak dapat digunakan sebagai pengidentifikasi: eval dan argument .
  • Upaya untuk menambahkan properti baru ke nilai primitif menimbulkan pengecualian.
  • Anda tidak dapat menggunakan pernyataan with.
  • Parameter fungsi tidak boleh memiliki nama yang sama.
  • Parameter fungsi tidak disinkronkan dengan nilai objek argumen.
  • Jika fungsi dipanggil sebagai fungsi (bukan sebagai metode), kata kunci this mengambil nilai undefined sebagai nilainya, bukan referensi ke objek global.
  • Kode yang diteruskan ke fungsi eval() dijalankan di kotak pasir, artinya kode masih dapat membaca dan mengubah variabel yang sudah ada, namun variabel dan fungsi yang dideklarasikan dalam kode yang diteruskan tidak akan keluar dari kotak pasir: "gunakan ketat"; function foo() ( var a = 10; eval("var x = 10; alert(x + a);"); alert(x); // Kesalahan. Variabel tersebut tidak ada ) foo();
  • Operan operator hapus hanya dapat berupa properti objek khusus atau elemen larik. Jika operan operator hapus adalah pengidentifikasi yang tidak memenuhi syarat, seperti nama variabel, nama fungsi, parameter fungsi, atau nama properti yang tidak dapat dikonfigurasi, kesalahan akan dimunculkan.
  • Anda tidak dapat menggunakan variabel yang tidak dideklarasikan dalam rantai penugasan: var a = b = 5; // Kesalahan. Variabel yang tidak dideklarasikan (b)
  • Mencoba menetapkan nilai ke properti yang tidak dapat ditulis atau membuat properti baru pada objek yang tidak dapat diperluas akan memunculkan pengecualian.
  • Mengakses properti argument.caller dan argument.callee melontarkan pengecualian.
  • Fungsi yang dideklarasikan sebagai FD di dalam blok berada dalam lingkup blok: ( foo(); // 1 function foo () ( alert(1); ) ) foo(); // Kesalahan. Fungsi foo tidak dideklarasikan.

Terkadang Anda akan melihat default, mode non-ketat yang disebut " " . Ini bukan istilah resmi, tetapi waspadalah, untuk berjaga-jaga.

Mode ketat JavaScript, yang diperkenalkan di ECMAScript 5, adalah cara untuk memilih di ke varian terbatas dari JavaScript, sehingga menyisih dari " " secara implisit. Mode ketat bukan hanya subset: itu dengan sengaja memiliki semantik yang berbeda dari kode normal. Peramban yang tidak mendukung mode ketat akan menjalankan kode mode ketat dengan perilaku yang berbeda dari browser yang melakukannya, jadi jangan mengandalkan mode ketat tanpa pengujian fitur untuk mendukung aspek yang relevan dari mode ketat. Kode mode ketat dan kode mode non-ketat dapat hidup berdampingan, sehingga skrip dapat ikut serta dalam mode ketat secara bertahap.

Mode ketat membuat beberapa perubahan pada semantik JavaScript normal:

  1. Menghilangkan beberapa kesalahan diam JavaScript dengan mengubahnya menjadi kesalahan lemparan.
  2. Memperbaiki kesalahan yang mempersulit mesin JavaScript untuk melakukan pengoptimalan: kode mode ketat terkadang dapat dibuat untuk berjalan lebih cepat daripada kode identik yang bukan mode ketat.
  3. Melarang beberapa sintaks yang kemungkinan akan ditentukan dalam versi ECMAScript yang akan datang.
(function() ( "use strict"; false.true = ""; // TypeError (14).sailing = "home"; // TypeError "with".you = "jauh"; // TypeError ))( );

Menyederhanakan penggunaan variabel

Mode ketat menyederhanakan bagaimana nama variabel dipetakan ke definisi variabel tertentu dalam kode. Banyak pengoptimalan kompiler mengandalkan kemampuan untuk mengatakan variabel itu X disimpan di itu lokasi: ini sangat penting untuk mengoptimalkan kode JavaScript sepenuhnya. JavaScript terkadang membuat pemetaan dasar nama ke definisi variabel dalam kode ini tidak mungkin dilakukan hingga runtime. Mode ketat menghapus sebagian besar kasus di mana hal ini terjadi, sehingga kompiler dapat mengoptimalkan kode mode ketat dengan lebih baik.

Pertama, mode ketat melarang dengan . Masalahnya dengan adalah bahwa nama apa pun di dalam blok mungkin memetakan ke properti objek yang diteruskan ke sana, atau ke variabel dalam lingkup sekitarnya (atau bahkan global), saat runtime: tidak mungkin untuk mengetahui yang mana sebelumnya. dengan kesalahan sintaksis, jadi tidak ada kemungkinan nama dalam a dengan untuk merujuk ke lokasi yang tidak diketahui saat runtime:

"gunakan ketat"; var x = 17; dengan (obj) ( // !!! kesalahan sintaks // Jika ini bukan mode ketat, apakah ini var x, atau // sebaliknya obj.x? Secara umum tidak mungkin // untuk mengatakan tanpa menjalankan kode, sehingga namanya tidak dapat // dioptimalkan.x; )

Alternatif sederhana untuk menugaskan objek ke variabel nama pendek, lalu mengakses properti terkait pada variabel itu, siap diganti dengan .

Kedua, . Dalam kode normal eval("var x;") memperkenalkan variabel x ke dalam fungsi sekitarnya atau lingkup global. Ini berarti bahwa, secara umum, dalam fungsi yang berisi panggilan ke eval setiap nama yang tidak mengacu pada argumen atau variabel lokal harus dipetakan ke definisi tertentu saat runtime (karena eval tersebut mungkin telah memperkenalkan variabel baru yang akan menyembunyikan variabel luar ). Dalam mode ketat eval membuat variabel hanya untuk kode yang sedang dievaluasi, jadi eval tidak dapat memengaruhi apakah suatu nama merujuk ke variabel luar atau beberapa variabel lokal:

Var x = 17; var evalX = eval(""gunakan ketat"; var x = 42; x;"); console.assert(x === 17); console.assert(evalX === 42);

Jika fungsi eval dipanggil oleh ekspresi bentuk eval(...) dalam kode mode ketat, kode tersebut akan dievaluasi sebagai kode mode ketat. Kode mungkin secara eksplisit memanggil mode ketat, tetapi tidak perlu melakukannya.

Fungsi strict1(str) ( "gunakan ketat"; return eval(str); // str akan diperlakukan sebagai kode mode ketat ) function strict2(f, str) ( "gunakan ketat"; kembalikan f(str); // tidak eval(...): str ketat jika dan hanya // jika memanggil mode ketat ) function nonstrict(str) ( return eval(str); // str ketat jika dan hanya // jika memanggil mode ketat ) strict1 (""Kode mode ketat!""); strict1(""gunakan ketat"; "Kode mode ketat!""); strict2(eval, ""Kode tidak ketat.""); strict2(eval, ""gunakan ketat"; "Kode mode ketat!""); nonstrict(""Kode tidak ketat.""); nonstrict(""gunakan ketat"; "Kode mode ketat!"");

Jadi nama dalam kode eval mode ketat berperilaku identik dengan nama dalam kode mode ketat yang tidak dievaluasi sebagai hasil eval .

Ketiga, mode ketat melarang menghapus nama biasa. hapus nama dalam mode ketat adalah kesalahan sintaksis:

"gunakan ketat"; varx; hapus x; // !!! kesalahan sintaks eval("var y; hapus y;"); // !!! kesalahan sintaks

Membuat eval dan argumen lebih sederhana

Mode ketat membuat argumen dan eval tidak terlalu ajaib. Keduanya melibatkan sejumlah besar perilaku magis dalam kode normal: eval untuk menambah atau menghapus pengikatan dan untuk mengubah nilai pengikatan, dan argumen dengan properti yang diindeks alias argumen bernama. Mode ketat membuat langkah besar untuk memperlakukan eval dan argumen sebagai kata kunci, meskipun perbaikan penuh tidak akan datang hingga ECMAScript edisi mendatang.

Pertama, nama eval dan argumen tidak dapat diikat atau ditetapkan dalam sintaks bahasa. Semua upaya untuk melakukannya adalah kesalahan sintaks:

"gunakan ketat"; nilai = 17; argumen++; ++nilai; var obj = ( atur p(argumen) ( ) ); vareval; coba ( ) tangkap (argumen) ( ) fungsi x(eval) ( ) argumen fungsi() ( ) var y = fungsi eval() ( ); var f = new Fungsi("argumen", ""gunakan ketat"; return 17;");

Kedua, kode mode ketat tidak membuat alias properti objek argumen yang dibuat di dalamnya. Dalam kode normal di dalam fungsi yang argumen pertamanya adalah arg , pengaturan arg juga menetapkan argumen , dan sebaliknya (kecuali tidak ada argumen yang diberikan atau argumen dihapus). objek argumen untuk fungsi mode ketat menyimpan argumen asli saat fungsi dipanggil.arguments[i] tidak melacak nilai dari argumen bernama yang sesuai, juga argumen bernama tidak melacak nilai dalam argumen yang sesuai[i] .

Fungsi f(a) ( "gunakan ketat"; a = 42; return ; ) var pair = f(17); console.assert(pasangan === 42); console.assert(pasangan === 17);

Ketiga, argument.callee tidak lagi didukung. Dalam argumen kode normal.callee mengacu pada fungsi terlampir. Kasus penggunaan ini lemah: cukup beri nama fungsi terlampir! Selain itu, argument.callee secara substansial menghalangi pengoptimalan seperti fungsi inlining, karena harus dimungkinkan untuk memberikan referensi ke fungsi yang tidak digariskan jika argument.callee diakses. argument.callee untuk fungsi mode ketat adalah properti yang tidak dapat dihapus yang melontarkan kesalahan saat disetel atau diambil:

"gunakan ketat"; var f = function() ( kembalikan argumen.callee; ); F(); // melempar TypeError

"Mengamankan" JavaScript

Mode ketat memudahkan untuk menulis JavaScript "aman". Beberapa situs web sekarang menyediakan cara bagi pengguna untuk menulis JavaScript yang akan dijalankan oleh situs web tersebut atas nama pengguna lain. JavaScript di browser dapat mengakses informasi pribadi pengguna, jadi JavaScript semacam itu harus diubah sebagian sebelum dijalankan, untuk menyensor akses ke fungsionalitas terlarang. Fleksibilitas JavaScript membuatnya tidak mungkin dilakukan secara efektif tanpa banyak pemeriksaan runtime. Fungsi bahasa tertentu sangat meresap sehingga melakukan pemeriksaan runtime memiliki biaya kinerja yang cukup besar. Beberapa penyesuaian mode ketat, plus mengharuskan JavaScript yang dikirimkan pengguna menjadi kode mode ketat dan dipanggil dengan cara tertentu, secara substansial mengurangi kebutuhan akan pemeriksaan runtime tersebut.

Pertama, nilai yang diteruskan sebagai this ke fungsi dalam mode ketat tidak dipaksa menjadi objek (a.k.a. "kotak"). Untuk fungsi normal, this selalu berupa objek: baik objek yang disediakan jika dipanggil dengan nilai objek this ; nilai, kotak, jika dipanggil dengan Boolean, string, atau angka this ; atau objek global jika dipanggil dengan undefined atau null this . (menggunakan panggilan , menerapkan, atau mengikat untuk menentukan tertentu this .) Tidak hanya kotak otomatis biaya kinerja, tetapi mengekspos objek global di browser adalah bahaya keamanan karena objek global menyediakan akses ke fungsionalitas yang harus dibatasi oleh lingkungan JavaScript "aman". Jadi untuk fungsi mode ketat, this yang ditentukan tidak dikotakkan ke dalam objek, dan jika tidak ditentukan, ini tidak akan ditentukan:

"gunakan ketat"; 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);

Itu berarti, antara lain, bahwa di browser tidak mungkin lagi mereferensikan objek jendela melalui ini di dalam fungsi mode ketat.

Kedua, dalam mode ketat tidak mungkin lagi untuk "menjalankan" tumpukan JavaScript melalui ekstensi yang biasa diterapkan ke ECMAScript. Dalam kode normal dengan ekstensi ini, saat fungsi fun sedang dipanggil, fun.caller adalah fungsi yang paling baru disebut fun , dan fun.arguments adalah argumen untuk pemanggilan fun .Jika fun dalam mode ketat, fun.caller dan fun.arguments adalah properti yang tidak dapat dihapus yang dilempar saat disetel atau diambil:

Fungsi dibatasi() ( "gunakan ketat"; pemanggil terbatas; // melempar Argumen TypeError terbatas; // melempar TypeError ) fungsi privilegedInvoker() ( kembali dibatasi(); ) privilegedInvoker();

Ketiga, argumen untuk fungsi mode ketat tidak lagi menyediakan akses ke variabel pemanggilan fungsi yang sesuai. Dalam beberapa argumen implementasi ECMAScript lama. pemanggil adalah objek yang propertinya adalah variabel alias dalam fungsi tersebut. Ini merupakan bahaya keamanan karena merusak kemampuan untuk sembunyikan nilai istimewa melalui abstraksi fungsi; itu juga menghalangi sebagian besar pengoptimalan. :

"gunakan ketat"; function fun(a, b) ( "use strict"; var v = 12; return argument.caller; // melempar TypeError ) fun(1, 2); // tidak mengekspos v (atau a atau b)

Membuka jalan untuk versi ECMAScript mendatang

Versi ECMAScript mendatang kemungkinan akan memperkenalkan sintaks baru, dan mode ketat di ECMAScript 5 menerapkan beberapa batasan untuk memudahkan transisi. Akan lebih mudah untuk membuat beberapa perubahan jika dasar dari perubahan tersebut dilarang dalam mode ketat.

Pertama, dalam mode ketat, daftar pendek pengidentifikasi menjadi kata kunci yang dipesan. Kata-kata ini adalah implements , interface , let , package , private , protected , public , static , dan yield . Dalam mode ketat, Anda tidak dapat memberi nama atau menggunakan variabel atau argumen dengan nama-nama ini.

Paket fungsi(dilindungi) ( // !!! "gunakan ketat"; implementasi var; // !!! antarmuka: // !!! sementara (benar) ( istirahat antarmuka; // !!! ) fungsi pribadi( ) ( ) // !!! ) fungsi menyenangkan(statis) ( "gunakan ketat"; ) // !!!

Dua peringatan khusus Mozilla: Pertama, jika kode Anda adalah JavaScript 1.7 atau lebih tinggi (misalnya dalam kode chrome atau saat menggunakan hak, tidak akan dapat menggunakan let / yield sebagai pengidentifikasi Kedua, sementara ES5 mencadangkan tanpa syarat kata-kata class , enum , export , extends , import , dan super , sebelum Firefox 5 Mozilla mencadangkannya hanya dalam mode ketat.

Kedua, . Dalam mode normal di browser, pernyataan fungsi diizinkan "di mana saja". Ini bukan bagian dari ES5 (atau bahkan ES3)! Ini adalah ekstensi dengan semantik yang tidak kompatibel di browser yang berbeda. Perhatikan bahwa pernyataan fungsi di luar level teratas diizinkan di ES2015.

"gunakan ketat"; if (benar) ( ​​fungsi f() ( ) // !!! kesalahan sintaks f(); ) untuk (var i = 0; i< 5; i++) { function f2() { } // !!! syntax error f2(); } function baz() { // kosher function eit() { } // also kosher }

Larangan ini bukan mode yang ketat karena pernyataan fungsi seperti itu merupakan perpanjangan dari ES5 dasar, tetapi ini adalah rekomendasi dari komite ECMAScript, dan browser akan menerapkannya.

Mode ketat di browser

Browser utama sekarang menerapkan mode ketat. Namun, jangan terlalu bergantung padanya karena masih banyak versi Browser yang digunakan di alam liar yang hanya mendukung sebagian untuk mode ketat atau tidak mendukungnya sama sekali (mis. Internet Explorer di bawah versi 10!). Mode ketat mengubah semantik. Mengandalkan perubahan tersebut akan menyebabkan kesalahan dan kesalahan pada browser yang tidak menerapkan mode ketat. Berhati-hatilah dalam menggunakan mode ketat, dan cadangkan ketergantungan pada mode ketat dengan pengujian fitur yang memeriksa apakah bagian yang relevan dari mode ketat diterapkan. Terakhir, buat yakin untuk uji kode Anda di browser yang mendukung dan tidak mendukung mode ketat. Jika Anda hanya menguji di browser yang tidak mendukung mode ketat, kemungkinan besar Anda akan mengalami masalah di browser yang mendukungnya, dan sebaliknya.

Spesifikasi

Spesifikasi Status Komentar
ECMAScript 5.1 (ECMA-262)
standar definisi awal. Lihat juga:
ECMAScript 2015 (Edisi ke-6, ECMA-262)
Definisi "Kode Mode Ketat" dalam spesifikasi itu.
standar Pembatasan dan pengecualian mode ketat
Draf Terbaru ECMAScript (ECMA-262)
Definisi "Kode Mode Ketat" dalam spesifikasi itu.
Draf