aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/javascript/reference/strict_mode
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
commit074785cea106179cb3305637055ab0a009ca74f2 (patch)
treee6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/ru/web/javascript/reference/strict_mode
parentda78a9e329e272dedb2400b79a3bdeebff387d47 (diff)
downloadtranslated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz
translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2
translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip
initial commit
Diffstat (limited to 'files/ru/web/javascript/reference/strict_mode')
-rw-r--r--files/ru/web/javascript/reference/strict_mode/index.html367
-rw-r--r--files/ru/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.html139
2 files changed, 506 insertions, 0 deletions
diff --git a/files/ru/web/javascript/reference/strict_mode/index.html b/files/ru/web/javascript/reference/strict_mode/index.html
new file mode 100644
index 0000000000..401d999d59
--- /dev/null
+++ b/files/ru/web/javascript/reference/strict_mode/index.html
@@ -0,0 +1,367 @@
+---
+title: Strict mode
+slug: Web/JavaScript/Reference/Strict_mode
+tags:
+ - ECMAScript 5
+ - JavaScript
+ - Strict Mode
+ - Строгий режим
+translation_of: Web/JavaScript/Reference/Strict_mode
+---
+<div>{{JsSidebar("More")}}</div>
+
+<p>Режим <em>strict</em> (<em>строгий</em> режим), введенный в <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript 5</a>, позволяет использовать более строгий вариант JavaScript. Это не просто подмножество языка: в нем сознательно используется семантика, отличающаяся от обычно принятой. Не поддерживающие строгий режим браузеры будут по-другому выполнять код, написанный для строгого режима, поэтому не полагайтесь на строгий режим без тестирования поддержки используемых особенностей этого режима. Строгий и обычный режим могут сосуществовать одновременно, а скрипт может переключаться в строгий режим по мере надобности.</p>
+
+<p>Строгий режим принёс ряд изменений в обычную семантику JavaScript. Во-первых, строгий режим заменяет исключениями некоторые ошибки, которые интерпретатор JavaScript ранее молча пропускал. Во-вторых, строгий режим исправляет ошибки, которые мешали движкам JavaScript выполнять оптимизацию -- в некоторых случаях код в строгом режиме может быть оптимизирован для более быстрого выполнения, чем код в обычном режиме. В-третьих, строгий режим запрещает использовать некоторые элементы синтаксиса, которые, вероятно, в следующих версиях ECMAScript получат особый смысл.</p>
+
+<p>Если вы хотите изменить свой код так, чтобы он работал в строгой версии JavaScript, посмотрите статью {{ jsxref("Strict_mode/Transitioning_to_strict_mode", "Переход к строгому режиму") }}.</p>
+
+<h2 id="Активизация_строгого_режима">Активизация строгого режима</h2>
+
+<p>Строгий режим применяется ко <em>всему скрипту</em> или к <em>отдельным функциям</em>. Он не может быть применён к блокам операторов, заключенных в фигурные скобки -- попытка использовать его в подобном контексте будет проигнорирована. Код в <code>eval</code>, <code>Function</code>, в аттрибутах обработчиков событий, в строках, переданных в <a href="/en/DOM/window.setTimeout" title="en/DOM/window.setTimeout"><code>setTimeout</code></a>, и т.п. рассматривается как законченный скрипт, и активизация строгого режима в нём выполняется ожидаемым образом.</p>
+
+<h3 id="Строгий_режим_для_скриптов">Строгий режим для скриптов</h3>
+
+<p>Чтобы активизировать строгий режим для всего скрипта, нужно поместить оператор <code>"use strict";</code> или <code>'use strict';</code> перед всеми остальными операторами скрипта (выдержать приведенный синтаксис буквально).</p>
+
+<pre class="brush: js">// Синтаксис переключения в строгий режим всего скрипта
+"use strict";
+var v = "Привет! Я скрипт в строгом режиме!";
+</pre>
+
+<p>В этой синтаксической конструкции кроется ловушка, в которую уже угодили даже <a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=579119">самые известные сайты</a>: нельзя бездумно объединять скрипты с разными режимами. Объединение скрипта в строгом режиме со скриптом в обычном выглядит как скрипт в строгом режиме! Справедливо и обратное: объединение обычного скрипта со строгим выглядит как нестрогий скрипт. Объединение только строгих или только обычных скриптов проходит без последствий, проблему вызывает совместное использование скриптов со строгим и обычным режимом. Поэтому рекомендуется включать строгий режим только на уровне функций (хотя бы в течение переходного периода).</p>
+
+<p>Вы также можете использовать подход "обёртывания" всего содержимого скрипта в функцию, для которой включён строгий режим. Это уменьшит возможность возникновения проблем при объединении скриптов, но одновременно потребует явно экспортировать из контекста функции все глобальные переменные.</p>
+
+<h3 id="Строгий_режим_для_функций">Строгий режим для функций</h3>
+
+<p>Аналогично, чтобы включить строгий режим для функции, поместите оператор <code>"use strict";</code> (или <code>'use strict';</code>) в тело функции перед любыми другими операторами.</p>
+
+<pre class="brush: js">function strict() {
+ // Строгий режим на уровне функции
+ "use strict";
+ function nested() { return "И я тоже!"; }
+ return "Привет! Я функция в строгом режиме! " + nested();
+}
+function notStrict() { return "Я не strict."; }
+</pre>
+
+<h3 id="Строгий_режим_для_модулей">Строгий режим для модулей</h3>
+
+<p>ECMAScript 2015 представил <a href="/ru/docs/Web/JavaScript/Reference/Statements/export">модули JavaScript</a> и, следовательно, 3-й способ войти в строгий режим. Все содержимое модулей JavaScript автоматически находится в строгом режиме, и для его запуска не требуется никаких инструкций.</p>
+
+<pre><code>function strict() {
+ // Потому что это модуль, я strict по-умолчанию
+}
+export default strict;</code></pre>
+
+<h2 id="Изменения_в_строгом_режиме">Изменения в строгом режиме</h2>
+
+<p>Строгий режим изменяет синтаксис и поведение среды исполнения. Изменения главным образом попадают в следующие категории: преобразование ошибок в исключения; изменения, упрощающие вычисление переменной в определённых случаях использования её имени; изменения, упрощающие <code>eval</code> и <code>arguments</code>; изменения, упрощающие написание "безопасного" JavaScript, и изменения, предвосхищающие дальнейшее развитие ECMAScript.</p>
+
+<h3 id="Преобразование_ошибок_в_исключения">Преобразование ошибок в исключения</h3>
+
+<p>Строгий режим превращает некоторые прощавшиеся ранее ошибки в исключения. JavaScript был разработан с расчётом на низкий порог вхождения, и временами он придаёт заведомо ошибочным операциям семантику нормального кода. Иногда это помогает срочно решить проблему, а иногда это создаёт худшие проблемы в будущем. Строгий режим расценивает такие ошибки как ошибки времени выполнения, для того чтобы они могли быть обнаружены и исправлены в обязательном порядке.</p>
+
+<p>Во-первых, строгий режим делает невозможным случайное создание глобальных переменных. В обычном JavaScript опечатка в имени переменной во время присваивания приводит к созданию нового свойства глобального объекта, и выполнение продолжается (хотя в современном JavaScript оно, вероятно, аварийно завершится в дальнейшем). Присваивания, которые могут случайно создать глобальную переменную, в строгом режиме выбрасывают исключение:</p>
+
+<pre class="brush: js">"use strict";
+ // Предполагая, что не существует глобальной переменной
+mistypeVaraible = 17; // mistypedVaraible, эта строка выбросит ReferenceError
+ // из-за опечатки в имени переменной</pre>
+
+<p>Во-вторых, строгий режим заставляет присваивания, которые всё равно завершились бы неудачей, выбрасывать исключения. Например, <code>NaN</code> -- глобальная переменная, защищённая от записи. В обычном режиме присваивание <code>NaN</code> значения ничего не делает; разработчик не получает никакого сообщения об ошибке. В строгом режиме присваивание <code>NaN</code> значения выбрасывает исключение. Любое присваивание, которое в обычном режиме завершается неудачей (присваивание значения свойству, защищённому от записи; присваивание значения свойству, доступному только на чтение; присваивание нового свойства <a href="/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions">нерасширяемому</a> объекту), в строгом режиме выбросит исключение:</p>
+
+<pre class="brush: js">"use strict";
+
+<code>// Присваивание значения глобальной переменной, защищенной от записи
+var undefined = 5; // выдаст TypeError
+var Infinity = 5; // выдаст TypeError
+</code>
+// Присваивание значения свойству, защищенному от записи
+var obj1 = {};
+Object.defineProperty(obj1, "x", { value: 42, writable: false });
+obj1.x = 9; // выдаст TypeError
+
+// Присваивание значения свойству, доступному только для чтения
+var obj2 = { get x() { return 17; } };
+obj2.x = 5; // выдаст TypeError
+
+// Задание нового свойства нерасширяемому объекту
+var fixed = {};
+Object.preventExtensions(fixed);
+fixed.newProp = "ohai"; // выдаст TypeError
+</pre>
+
+<p>В-третьих, в строгом режиме попытки удалить неудаляемые свойства будут вызывать исключения (в то время как прежде такая попытка просто не имела бы эффекта):</p>
+
+<pre class="brush: js">"use strict";
+delete Object.prototype; // выдаст TypeError
+</pre>
+
+<p>В-четвёртых, строгий режим требует, чтобы все свойства, перечисленные в сериализованном объекте, встречались только один раз. В обычном коде имена свойств могут дублироваться, а значение свойства определяется последним объявлением. Но, в таком случае, дублирование -- просто почва для багов, если код редактируется с тем, чтобы поменять значение свойства как-то по-другому, кроме изменения последнего объявления. Дублирование имён свойств в строгом режиме является синтаксической ошибкой:</p>
+
+<div class="note">
+<p>Это уже не является проблемой в ECMAScript 2015 ({{bug(1041128)}}).</p>
+</div>
+
+<pre class="brush: js">"use strict";
+var o = { p: 1, p: 2 }; // !!! синтаксическая ошибка
+</pre>
+
+<p>В-пятых, строгий режим требует, чтобы имена аргументов в объявлении функций встречались только один раз. В обычном коде последний повторённый аргумент скрывает предыдущие аргументы с таким же именем. Эти предыдущие аргументы всё ещё доступны через <code>arguments[i]</code>, так что они не полностью потеряны. Тем не менее, такое сокрытие несёт в себе мало смысла и, скорее всего, не имеет под собой цели (например, может скрывать опечатку), поэтому в строгом режиме дублирование имён аргументов является синтаксической ошибкой:</p>
+
+<pre class="brush: js">function sum(a, a, c) { // !!! синтаксическая ошибка
+ "use strict";
+ return a + a + c; // ошибка, если код был запущен
+}
+</pre>
+
+<p>В-шестых, строгий режим запрещает синтаксис восьмеричной системы счисления. Восьмеричный синтаксис не является частью ECMAScript, но поддерживается во всех браузерах с помощью дописывания нуля спереди к восьмеричному числу: <code>0644 === 420</code> и <code>"\045" === "%"</code>. В ECMAScript 2015 восьмеричное число поддерживается также с помощью дописывания перед числом "<code>0o</code>". Т.е.</p>
+
+<pre><code>var a = 0o10; // ES2015: Восмеричное</code>
+</pre>
+
+<p>Иногда начинающие разработчики думают, что ведущий ноль не имеет семантического значения, и используют его для выравнивания -- но это меняет значение числа! Восьмеричный синтаксис редко бывает полезен и может быть неправильно использован, поэтому строгий режим считает восьмеричные числа синтаксической ошибкой:</p>
+
+<pre class="brush: js">"use strict";
+var sum = 015 + // !!! синтаксическая ошибка
+ 197 +
+ 142;
+
+<code>var sumWithOctal = 0o10 + 8;
+console.log(sumWithOctal); // 16</code>
+</pre>
+
+<p>В-седьмых, строгий режим в ECMAScript 2015 запрещает установку свойств {{Glossary("primitive")}} значениям. Без строгого режима, установка свойств просто игнорируется (no-op), со строгим режимом, однако, выдает {{jsxref ("TypeError")}}.</p>
+
+<pre><code>(function() {
+'use strict';
+
+false.true = ''; // TypeError
+(14).sailing = 'home'; // TypeError
+'with'.you = 'far away'; // TypeError
+
+})();</code></pre>
+
+<h3 id="Упрощение_работы_с_переменными">Упрощение работы с переменными</h3>
+
+<p>Строгий режим упрощает сопоставление имени переменной с местом ее определения в коде. Многие оптимизации времени компиляции полагаются на возможность считать, что переменная <em>X</em> хранится в <em>этом конкретном </em>месте исходного кода. Иногда, при компиляции JavaScript простое сопоставление имени переменной с местом ее определения в коде не возможно, без выполнения того самого кода. Строгий же режим исключает большинство таких случаев, благодаря чему оптимизации компилятора работают эффективнее.</p>
+
+<p>Во-первых, строгий режим запрещает использование <code>with</code>. Проблема с <code>with</code> в том, что во время выполнения любое имя внутри блока может ссылаться как на свойство обрабатываемого объекта, так и на переменную в окружающем (или даже в глобальном) контексте -- невозможно знать об этом заранее. Строгий режим считает <code>with</code> синтаксической ошибкой, поэтому не остаётся шанса использовать имя переменной внутри <code>with</code> для ссылки на неизвестное место во время выполнения:</p>
+
+<pre class="brush: js">"use strict";
+var x = 17;
+with (obj) { // !!! синтаксическая ошибка
+ // Если код не в строгом режиме, то будет ли <code>x </code>ссылаться на переменную var x, или
+ // на свойство obj.x? Предугадать без запуска кода невозможно,
+ // следовательно такой код не может быть эффективно оптимизирован.
+ x;
+}
+</pre>
+
+<p>Простая альтернатива <code>with</code> уже существует -- присваивание объекта переменной с коротким именем и затем доступ к нужному свойству как свойству этой переменной.</p>
+
+<p>Во-вторых, <a href="http://whereswalden.com/2011/01/10/new-es5-strict-mode-support-new-vars-created-by-strict-mode-eval-code-are-local-to-that-code-only/"><code>eval</code> в строгом режиме не добавляет новых переменных в окружающий контекст</a>. В обычном режиме, при вызове <code>eval("var x;")</code> переменная <code>x</code> добавится в область видимости окружающей функции либо в глобальный контекст. В общем случае, это означает, что в каждой функции, в которой присутствует вызов <code>eval</code>, имена переменных которые не ссылаются на аргумент или локальную переменную, должны сопоставляться с местом их определения в коде только во время выполнения (потому что <code>eval</code> мог ввести новую переменную, которая может перекрыть внешнюю переменную). В строгом режиме <code>eval</code> создаёт переменные только в контексте выполняемого кода, так что <code>eval</code> не может повлиять на то, ссылается ли имя на локальную или на внешнюю переменную:</p>
+
+<pre class="brush: js">var x = 17;
+var evalX = eval("'use strict'; var x = 42; x");
+console.assert(x === 17);
+console.assert(evalX === 42);
+</pre>
+
+<p>Соответственно, если функция <code>eval</code> вызвана непосредственно в форме выражения <code>eval(...)</code>, то внутри кода в строгом режиме, передаваемый в неё код будет выполнен в строгом режиме. Передаваемый код может содержать в себе включение строгого режима, но в этом нет необходимости.</p>
+
+<pre class="brush: js">function strict1(str) {
+ "use strict";
+ return eval(str); // str будет выполнен как код строгого режима
+}
+function strict2(f, str) {
+ "use strict";
+ return f(str); // не eval(...): str выполнится в строгом режиме только в том
+ // случае, если в нем содержится вызов строгого режима
+}
+function nonstrict(str) {
+ return eval(str); // str выполнится в строгом режиме только в том
+ // случае, если в нем содержится вызов строгого режима
+}
+strict1("'Строгий режим!'");
+strict1("'use strict'; 'Строгий режим!'");
+strict2(eval, "'Не строгий режим.'");
+strict2(eval, "'use strict'; 'Строгий режим!'");
+nonstrict("'Не строгий режим.'");
+nonstrict("'use strict'; 'Строгий режим!'");
+</pre>
+
+<p>Таким образом, имена в строгом коде, передаваемом в <code>eval</code><font face="Courier New, Andale Mono, monospace">, </font>ведут себя так же, как имена в нестрогом коде, передаваемом в <code>eval</code> внутри строгого режима.</p>
+
+<p>В-третьих, строгий режим запрещает удаление простых имён. <code>delete name</code> в строгом режиме является синтаксической ошибкой:</p>
+
+<pre class="brush: js"><code>'use strict';
+
+var x;
+delete x; // !!! </code>синтаксическая ошибка<code>
+
+eval('var y; delete y;'); // !!! </code>синтаксическая ошибка</pre>
+
+<h3 id="Упрощение_eval_и_arguments">Упрощение <code>eval</code> и <code>arguments</code></h3>
+
+<p>В строгом режиме снижается количество странностей в поведении <code>arguments</code> и <code>eval</code>, оба из которых примешивают определённое количество магии в обычный код. Так <code>eval</code> добавляет или удаляет переменные и меняет их значения, а переменная <code>arguments</code> может удивить своими проиндексированными свойствами, которые являются ссылками (синонимами) для проименованных аргументов функции. Строгий режим делает большой шаг в прояснении этих двух ключевых слов, но полное их обуздание произойдет лишь в следующей редакции ECMAScript.</p>
+
+<p>Во-первых, ключевые слова <code>eval</code> и <code>arguments</code> не могут быть переопределены или изменены. Все подобные попытки это сделать являются синтаксическими ошибками:</p>
+
+<pre class="brush: 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;");
+</pre>
+
+<p>Во-вторых, в строгом режиме поля объекта <code>arguments</code> не связаны с проименованными аргументами функции, а являются их продублированными копиями значений. В обычном коде внутри функции, первым аргументом которой является <code>arg</code>, изменение значения переменной <code>arg</code> также меняет значение и у поля <code>arguments[0]</code>, и наоборот (кроме случаев, когда аргумент в функцию не передан, или <code>arguments[0]</code> удалён). В строгом режиме <code>arguments</code> хранит копии значений аргументов переданных при вызове функции. <code>arguments[i]</code> не отслеживает изменений соответствующего именованного аргумента, и именованный аргумент не отслеживает значение соответствующего arguments[i].</p>
+
+<pre class="brush: 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);
+</pre>
+
+<p>В-третьих, свойство <code>arguments.callee</code> больше не поддерживается. В обычном коде свойство <code>arguments.callee</code> ссылается на саму функцию для вызова которой и был создан объект <code>arguments</code>. Малоприменимое свойство, так как функция заранее известна, и к ней можно обратиться и по ее имени непосредственно. Более того, <code>arguments.callee</code> значительно затрудняет такую оптимизацию, как <a href="https://ru.wikipedia.org/wiki/Межпроцедурная_оптимизация#Инлайнинг">инлайнинг</a>, потому как должна быть сохранена возможность обратиться к незаинлайненой функции на случай, если присутствует обращение к arguments.callee. В строгом режиме arguments.callee превращается в неудаляемое свойство, которое выбрасывает предостерегающее исключение при любой попытке обращения к нему:</p>
+
+<pre class="brush: js">"use strict";
+var f = function() { return arguments.callee; };
+f(); // выдаст TypeError
+</pre>
+
+<h3 id="Обезопасенный_JavaScript">"Обезопасенный" JavaScript</h3>
+
+<p>Строгий режим упрощает написание "безопасного" JavaScript кода. Сейчас некоторые веб-сайты предоставляют пользователям возможность писать JavaScript, который будет выполняться на сайте <em>от имени других пользователей. </em>В браузерах, JavaScript может иметь доступ к приватной информации пользователя, поэтому, в целях ограничения доступа к запретной функциональности, такой JavaScript перед выполнением должен быть частично преобразован. Гибкость JavaScript делает это практически невозможным без многочисленных проверок во время исполнения. Функционал, исполняемый языком иногда столь массивен, что выполнение любых дополнительных проверок во время исполнения скрипта приведет к значительной потере производительности. Однако, некоторые особенности строгого режима, плюс обязательное требование того, чтобы JavaScript, загруженный пользователем, имел строгий режим и вызывался определенным способом, существенно снижают потребность в таких проверках.</p>
+
+<p>Во-первых, значение, передаваемое в функцию как <code>this</code>, в строгом режиме не приводится к объекту (не "упаковывается"). В обычной функции <code>this</code> всегда представляет собой объект: либо это непосредственно объект, в случае вызова с <code>this</code>, представляющим объект-значение; либо значение, упакованное в объект, в случае вызова с <code>this</code> типа Boolean, string, или number; либо глобальный объект, если тип <code>this</code> это <code>undefined</code> или <code>null</code>. (Для точного определения конкретного <code>this</code> используйте <code>{{jsxref('Global_Objects/Function/call', 'call')}}</code>, <code>{{jsxref('Global_Objects/Function/apply', 'apply')}}</code>, или <code>{{jsxref('Global_Objects/Function/bind', 'bind')}}</code>.) Автоматическая упаковка не только снижает производительность, но и выставляет на показ глобальный объект, что в браузерах является угрозой безопасности, потому что глобальный объект предоставляет доступ к функциональности, которая должна быть ограничена в среде "безопасного" JavaScript. Таким образом, для функции в строгом режиме точно определённый <code>this</code> не упаковывается в объект, а если не определён точно, <code>this</code> является <code>undefined</code>:</p>
+
+<pre class="brush: 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);
+</pre>
+
+<p>Во-вторых, в строгом режиме больше не представляется возможным осуществлять "прогонку" стека JavaScript посредством базовых расширений ECMAScript. В обычном коде, использующем эти расширения, когда функция <code>fun</code> находится в процессе своего вызова, <code>fun.caller</code> представляет собой функцию, вызвавшую <code>fun</code>, а <code>fun.arguments</code> это <code>аргументы</code> для данного вызова <code>fun</code>. Оба расширения являются проблемными для "безопасного" JavaScript, так как они позволяют "безопасному" коду получить доступ к "привилегированным" функциям и их (потенциально небезопасным) аргументам. Если <code>fun</code> находится в строгом режиме, то <code>fun.caller</code>, так же как и <code>fun.arguments,</code> представляют собой неудаляемые свойства, которые приведут к вызову исключения при попытке их чтения или записи:</p>
+
+<pre class="brush: js">function restricted() {
+ "use strict";
+
+ restricted.caller; // выдаст TypeError
+ restricted.arguments; // выдаст TypeError
+}
+function privilegedInvoker() {
+ return restricted();
+}
+privilegedInvoker();
+</pre>
+
+<p>В-третьих, в функциях строгого режима свойство <code>arguments</code> больше не предоставляет доступ к переменным, созданным внутри функции. В некоторых предыдущих реализациях ECMAScript <code>arguments.caller</code> представлял собой объект, свойства которого являлись ссылками на переменные, созданные внутри функции при её вызове. Это представляет собой <a class="external" href="http://stuff.mit.edu/iap/2008/facebook/">угрозу безопасности</a>, так как нарушает возможность скрывать приватные данные внутри функций (замыканий). Также это делает невозможными большинство оптимизаций. Исходя из этих причин, ни один из современных браузеров не реализует этого поведения. Но все же, ввиду своей исторической функциональности, <code>arguments.caller</code> для функций в строгом режиме всё ещё является неудаляемым свойством, которое вызывает исключение при попытке его чтения или записи:</p>
+
+<pre class="brush: js">"use strict";
+function fun(a, b) {
+ "use strict";
+
+ var v = 12;
+ return arguments.caller; // выдаст TypeError
+}
+fun(1, 2); // не выводит v (или a, или b)
+</pre>
+
+<h3 id="Подготовка_почвы_для_будущих_версий_ECMAScript">Подготовка почвы для будущих версий ECMAScript</h3>
+
+<p>В будущих версиях ECMAScript с высокой вероятностью появится новый синтаксис, и для упрощения перехода на новые версии, в строгом режиме ECMAScript 5 введено несколько ограничений. Всегда проще вносить изменения в стандарт, если заранее подготовить для них основу в строгом режиме.</p>
+
+<p>Во-первых, в строгом режиме зарезервирован для использования следующий список ключевых слов: <code>implements</code>, <code>interface</code>, <code>let</code>, <code>package</code>, <code>private</code>, <code>protected</code>, <code>public</code>, <code>static</code> и <code>yield</code>. В строгом режиме, следовательно, вы не можете задействовать эти слова для именования или обращения к переменным или аргументам.</p>
+
+<pre class="brush: js">function package(protected) { // !!!
+ "use strict";
+ var implements; // !!!
+
+ interface: // !!!
+ while (true) {
+ break interface; // !!!
+ }
+
+ function private() { } // !!!
+}
+function fun(static) { 'use strict'; } // !!!
+
+</pre>
+
+<p>Два замечания, специфичных для Mozilla: Первое, если ваш код создан на JavaScript 1.7 или выше (например, chrome code, или тег <code>&lt;script type=""&gt;</code> заполнен правильно), и применен строгий режим, то <code>let</code> и <code>yield</code> имеют ту же функциональность, которая у них была изначально, когда они только появились. Однако в веб, в строгом коде загруженном через <code>&lt;script src=""&gt;</code> или <code>&lt;script&gt;...&lt;/script&gt;</code>, нельзя будет использовать <code>let</code>/<code>yield</code> в качестве идентификаторов. Второе, в то время как ES5 зарезервировал слова <code>class</code>, <code>enum</code>, <code>export</code>, <code>extends</code>, <code>import</code> и <code>super</code> для любого режима, в Firefox 5 Mozilla они были зарезервированы намного раньше и лишь для строгого режима.</p>
+
+<p>Во-вторых, <a class="external" href="http://whereswalden.com/2011/01/24/new-es5-strict-mode-requirement-function-statements-not-at-top-level-of-a-program-or-function-are-prohibited/">в строгом режиме запрещается объявление функций глубже самого верхнего уровня скрипта или функции</a>. В обычном коде в браузерах, объявление функций позволено "везде", <em>что не является частью ES5 (или даже ES3!)</em> Это расширение различных браузеров, не имеющее общего совместимого подхода. Есть надежда, что в последующих редакциях ECMAScript будет определена новая семантика для объявления функций вне верхнего уровня скрипта или функции. <a class="external" href="http://wiki.ecmascript.org/doku.php?id=conventions:no_non_standard_strict_decls">Запрет на объявление таких функций в строгом режиме</a> производит "зачистку" для спецификации в будущем релизе ECMAScript:</p>
+
+<pre class="brush: js">"use strict";
+if (true) {
+ function f() { } // !!! синтаксическая ошибка
+ f();
+}
+for (var i = 0; i &lt; 5; i++) {
+ function f2() { } // !!! синтаксическая ошибка
+ f2();
+}
+function baz() { // верно
+ function eit() { } // тоже верно
+}
+</pre>
+
+<p>Данный запрет не является особенностью строгого режима, потому что такое объявление функций является одним из расширений основного ES5. Но это рекомендация комитета ECMAScript, и браузеры реализуют ее.</p>
+
+<h2 id="Строгий_режим_в_браузерах">Строгий режим в браузерах</h2>
+
+<p>В большинстве браузеров в настоящее время строгий режим реализован. Однако не стоит впадать в слепую зависимость от него, потому что существует множество <a class="external external-icon" href="http://caniuse.com/use-strict" rel="external" title="caniuse.com availability of strict mode">Версий браузеров, поддерживающих строгий режим лишь частично</a> или вовсе не поддерживающих оный (например, Internet Explorer ниже версии 10!). <em>Строгий режим изменяет семантику.</em> Надежда на эти изменения приведет к ошибкам и погрешностям в браузерах, в которых строгий режим не реализован. Проявляйте осторожность при использовании строгого режима, и подкрепляйте надежность строгого режима тестами особенностей, которые проверяют, насколько верно реализованы его фрагменты. Наконец, старайтесь <em>тестировать свой код в браузерах, как поддерживающих, так и не поддерживающих строгий режим</em>. Если вы проводите тестирование только в тех браузерах, которые не поддерживают строгий режим, то вполне вероятно у вас появятся проблемы в браузерах, его поддерживающих, и наоборот.</p>
+
+<h2 id="Спецификации">Спецификации</h2>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <th scope="col">Спецификация</th>
+ <th scope="col">Статус</th>
+ <th scope="col">Комментарий</th>
+ </tr>
+ <tr>
+ <td>{{SpecName('ES5.1', '#sec-10.1.1', 'Strict Mode Code')}}</td>
+ <td>{{Spec2('ES5.1')}}</td>
+ <td>Основные определения. См. также: <a href="http://www.ecma-international.org/ecma-262/5.1/#sec-C">Strict mode restriction and exceptions</a></td>
+ </tr>
+ <tr>
+ <td>{{SpecName('ES6', '#sec-strict-mode-code', 'Strict Mode Code')}}</td>
+ <td>{{Spec2('ES6')}}</td>
+ <td><a href="http://www.ecma-international.org/ecma-262/6.0/#sec-strict-mode-of-ecmascript">Ограничения и исключения строгого режима (Strict mode restriction and exceptions</a>)</td>
+ </tr>
+ <tr>
+ <td>{{SpecName('ESDraft', '#sec-strict-mode-code', 'Strict Mode Code')}}</td>
+ <td>{{Spec2('ESDraft')}}</td>
+ <td><a href="https://tc39.github.io/ecma262/#sec-strict-mode-of-ecmascript">Ограничения и исключения строгого режима (Strict mode restriction and exceptions</a>)</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="См._также">См. также</h2>
+
+<ul>
+ <li><a class="external" href="http://whereswalden.com/2010/09/08/new-es5-strict-mode-support-now-with-poison-pills/" title="http://whereswalden.com/2010/09/08/new-es5-strict-mode-support-now-with-poison-pills/">Where's Walden? » New ES5 strict mode support: now with poison pills!</a></li>
+ <li><a class="external" href="http://whereswalden.com/2011/01/24/new-es5-strict-mode-requirement-function-statements-not-at-top-level-of-a-program-or-function-are-prohibited/" title="http://whereswalden.com/2011/01/24/new-es5-strict-mode-requirement-function-statements-not-at-top-level-of-a-program-or-function-are-prohibited/">Where's Walden? » New ES5 strict mode requirement: function statements not at top level of a program or function are prohibited</a></li>
+ <li><a class="external" href="http://whereswalden.com/2011/01/10/new-es5-strict-mode-support-new-vars-created-by-strict-mode-eval-code-are-local-to-that-code-only/" title="http://whereswalden.com/2011/01/10/new-es5-strict-mode-support-new-vars-created-by-strict-mode-eval-code-are-local-to-that-code-only/">Where's Walden? » New ES5 strict mode support: new vars created by strict mode eval code are local to that code only</a></li>
+ <li><a class="external" href="http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/" title="http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/">John Resig - ECMAScript 5 Strict Mode, JSON, and More</a></li>
+ <li><a class="external" href="http://dmitrysoshnikov.com/ecmascript/es5-chapter-2-strict-mode/">ECMA-262-5 in detail. Chapter 2. Strict Mode.</a></li>
+ <li><a class="external" href="http://kangax.github.io/compat-table/strict-mode/">Strict mode compatibility table</a></li>
+</ul>
diff --git a/files/ru/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.html b/files/ru/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.html
new file mode 100644
index 0000000000..8bbf8096cf
--- /dev/null
+++ b/files/ru/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.html
@@ -0,0 +1,139 @@
+---
+title: Переход к строгому режиму
+slug: Web/JavaScript/Reference/Strict_mode/Transitioning_to_strict_mode
+tags:
+ - Advanced
+ - JavaScript
+translation_of: Web/JavaScript/Reference/Strict_mode/Transitioning_to_strict_mode
+---
+<div>{{jsSidebar("More")}}</div>
+
+<p>В ECMAScript 5 введен {{jsxref('Strict_mode', 'строгий режим')}}, который реализован во всех основных браузерах (включая IE10). В то время как включение интерпретации браузерами кода в строгом режиме делается очень просто (достаточно добавить <code>"use strict";</code> в верхней части вашего исходного кода), для адаптации уже существующего кода к строгому режиму потребуется немного больше работы.</p>
+
+<p>Цель этой статьи: предоставить для разработчиков руководство по переходу к строгому режиму.</p>
+
+<h2 id="Постепенный_переход">Постепенный переход</h2>
+
+<p>Строгий режим был спроектирован таким образом, чтобы переход к нему можно было сделать постепенно. Каждый файл можно переводить к строгому режиму поодиночке, и даже есть возможность включить строгий режим для каждой функции по отдельности.</p>
+
+<h2 id="Различия_non-strict_и_strict_режимов">Различия non-strict и strict режимов</h2>
+
+<h3 id="Синтаксические_ошибки">Синтаксические ошибки</h3>
+
+<p>При добавлении <code>"use strict";</code> следующие случаи вызывают {{jsxref("SyntaxError")}} до выполнения скрипта:</p>
+
+<ul>
+ <li>Восьмеричное представление числа <code>var n = 023;</code></li>
+ <li>Использование оператора <code>{{jsxref('Statements/with', 'with')}}</code></li>
+ <li>Использование <code>{{jsxref('Operators/delete', 'delete')}}</code> на имени переменной <code>delete myVariable;</code></li>
+ <li>Использование <code>{{jsxref('Global_Objects/eval', 'eval')}}</code> или <code>{{jsxref('Functions/arguments', 'arguments')}}</code> как переменную или аргумент функции</li>
+ <li>Использование одного из новых {{jsxref('Lexical_grammar', 'зарезервированных ключевых слов', 'Ключевые_слова')}} (зарезервированных для ECMAScript 6): <code>implements</code>, <code>interface</code>, <code>let</code>, <code>package</code>, <code>private</code>, <code>protected</code>, <code>public</code>, <code>static</code>, и <code>yield</code></li>
+ <li>Объявление функций в блоках <code>if (a &lt; b) { function f() {} }</code></li>
+ <li>Очевидные ошибки
+ <ul>
+ <li>Объявление дважды свойства с одним и тем же именем в литерале объекта <code>{a: 1, b: 3, a: 7}</code>. Это уже изменилось в ECMAScript 6 ({{bug(1041128)}}).</li>
+ <li>Объявление нескольких аргументов функции с одним и тем же именем <code>function f(a, b, b) {}</code></li>
+ </ul>
+ </li>
+</ul>
+
+<p>Эти ошибки хороши тем, что обличают скользкие, едва уловимые ошибки и плохие практики написания кода.</p>
+
+<h3 id="Новые_ошибки_времени_выполнения_runtime_errors">Новые ошибки времени выполнения (runtime errors)</h3>
+
+<p>Ранее JavaScript не показывал никаких ошибок и предупреждений в некоторых случаях выполнения некорректного кода. Строгий режим выбрасывает исключения в таких случаях. Если в вашем коде есть такие случаи, тестирование будет необходимо, чтобы убедиться, что ничего не сломалось после перехода к строгому режиму. Ещё раз это может случится на уровне детализации функции.</p>
+
+<h4 id="Установка_значения_необъявленной_переменной">Установка значения необъявленной переменной</h4>
+
+<pre class="brush: js">function f(x) {
+ "use strict";
+ var a = 12;
+ b = a + x * 35; // error!
+}
+f(42);
+</pre>
+
+<p>Здесь изменяется значение глобального объекта, что редко является ожидаемым эффектом. Если вы действительно хотите изменить значение глобального объекта, передайте его в качестве аргумента функции и явно присвойте его как свойство:</p>
+
+<pre class="brush: js">var global = this; // в верхнем контексте "this" всегда
+ // ссылается на глобальный объект
+function f(x) {
+ "use strict";
+ var a = 12;
+ global.b = a + x * 35;
+}
+f(42);
+</pre>
+
+<h4 id="Попытка_удалить_неконфигурируемое_свойство">Попытка удалить неконфигурируемое свойство</h4>
+
+<pre class="brush: js">"use strict";
+delete Object.prototype; // error!
+</pre>
+
+<p>В нестрогом режиме этот код может молчаливо выполниться неудачей и ничего не сделать, вопреки ожиданиям.</p>
+
+<h4 id="Отравленные_аргументы_arguments_и_свойства_функции">Отравленные аргументы (arguments) и свойства функции</h4>
+
+<p>Обращение к <code>arguments.callee</code>, <code>arguments.caller</code>, <code>anyFunction.caller</code>, или <code>anyFunction.arguments</code> выбросит исключение в строгом режиме. Единственный законный способ повторного использования функции как в:</p>
+
+<pre class="brush: js">// Пример взят из vanillajs: http://vanilla-js.com/
+var s = document.getElementById('thing').style;
+s.opacity = 1;
+(function() {
+ if((s.opacity-=.1) &lt; 0)
+ s.display = "none";
+ else
+ setTimeout(arguments.callee, 40);
+})();</pre>
+
+<p>может быть переписан как:</p>
+
+<pre class="brush: js">"use strict";
+var s = document.getElementById('thing').style;
+s.opacity = 1;
+(function fadeOut() { // имя функции
+ if((s.opacity-=.1) &lt; 0)
+ s.display = "none";
+ else
+ setTimeout(fadeOut, 40); // используется имя функции
+})();</pre>
+
+<h3 id="Семантические_различия">Семантические различия</h3>
+
+<p>Эти различия очень тонкие. Вполне возможно, что тесты не поймают этот тип едва уловимых отличий. Вероятно, потребуется тщательная рецензия кода, чтобы удостовериться, что эти различия не влияют на семантику вашего кода. К счастью, этот анализ может быть сделан постепенно, спускаясь вниз к реализации каждой конкретной функции.</p>
+
+<h4 id="this_в_вызовах_функции"><code>this</code> в вызовах функции</h4>
+
+<p>В функциях как <code>f()</code>, значением <code>this</code> является глобальный объект. В строгом режиме он теперь равен <code>undefined</code>. Когда функция вызывалась с помощью <code>{{jsxref('Global_Objects/Function/call', 'call')}}</code> или <code>{{jsxref('Global_Objects/Function/apply', 'apply')}}</code>, если значением был примитив, он упаковывался в соответствующий объект (или в глобальный объект для <code>undefined</code> и <code>null</code>). В строгом режиме значение передается без каких-либо преобразований и замен.</p>
+
+<h4 id="arguments_не_является_псевдонимом_именованных_аргументов_функции"><code>arguments</code> не является псевдонимом именованных аргументов функции</h4>
+
+<p>В нестрогом режиме изменение значения в объекте <code>arguments</code> изменяло соответствующий именованный аргумент функции. Это усложняло оптимизацию кода для движков JavaScript и сам код становился менее читабельным и понятным. В строгом режиме объект <code>arguments</code> создается и инициализируется с теми же значениями, что и именованные аргументы, но изменения объекта arguments или именованных аргументов теперь никак не влияют друг на друга.</p>
+
+<h4 id="Изменения_в_eval">Изменения в <code>eval</code></h4>
+
+<p>В строгом режиме eval не создает новой переменной в той области видимости, где был вызван. Также, конечно, в строгом режиме, строка выполняется с правилами строгого режима. Потребуется провести тщательное тестирование, чтобы убедиться, что ничего не сломалось. Не использовать eval, если он вам действительно не нужен, может быть другим прагматичным решением.</p>
+
+<h2 id="Строго-нейтральный_код">Строго-нейтральный код</h2>
+
+<p>Потенциальный "недостаток" перевода кода в строгий режим - это отличия в семантике старых браузеров, в которых он не реализован. В некоторых редких случаях (как при неудачной конкатенации и минификации) ваш код может не запускаться в режиме, в котором вы его писали и тестировали. Здесь несколько правил, как сделать ваш код строго-нейтральным (strictness-neutral):</p>
+
+<ol>
+ <li>Пишите ваш код в строгом режиме и убедитесь в отсутствии ошибок только строго режима (из секции выше "Новые ошибки времени выполнения").</li>
+ <li>Держитесь подальше от семантических различий:
+ <ol>
+ <li><code>eval</code>: используйте только тогда, когда вы знаете что делаете</li>
+ <li><code>arguments</code>: всегда обращайтесь к аргументам функции через их имя или сделайте копию объекта arguments, используя:<br>
+ <code>var args = Array.prototype.slice.call(arguments)</code><br>
+ в самой первой строчке вашей функции</li>
+ <li><code>this</code>: используйте <code>this</code> только тогда, когда он ссылается на объект, созданный вами.</li>
+ </ol>
+ </li>
+</ol>
+
+<h2 id="Смотрите_также">Смотрите также</h2>
+
+<ul>
+ <li>{{jsxref('Strict_mode', 'Строгий режим')}}</li>
+</ul>