Статьи

Строгий режим JavaScript

В пятом издании спецификации ECMAScript появился строгий режим. Строгий режим накладывает слой ограничений на JavaScript — предназначенный для защиты вас от более опасных аспектов языка.

В ходе исследования этой статьи я написал 38 тестов, охватывающих все правила строгого режима, определенные в спецификации ES5 . Вы можете увидеть, как формируется ваш любимый браузер, нажав здесь .

Код для каждого теста воспроизводится в конце статьи, чтобы помочь понять спецификацию. Вы также можете запустить тесты вручную, скопировав и вставив исходный код в консоль. Полный исходный код находится на моем репозитории github .

Firefox 4 и IE10 (превью 1) уже полностью поддерживают строгий режим, а Chrome 12 уже почти готов. Строгий режим здесь, чтобы остаться — давайте погрузимся в …

Как вызвать строгий режим?

Добавление «используйте строгий» в качестве первого утверждения в вашем коде JavaScript приведет к строгому режиму для всего источника…

"use strict";
2 012; //Octal literal throws a SyntaxError in Strict Mode

В качестве альтернативы вы можете ограничить применение строгого режима данной функцией, добавив выражение «использовать строго» в первую строку тела функции…

012; //No Error (Strict Mode not enforced globally)
2 function foo() {
3 "use strict";
4 x=3; //Strict Mode will throw an error for implicit globals
5 }
6 foo(); //ReferenceError (Strict Mode is enforced for function foo)

Отражают ли функции директивы строгого режима своих внешних функций?

Внутренние функции, определенные внутри внешней функции, которая несет директиву «использовать строгое», также будут подчиняться строгому режиму…

var wrapper = function(fn) {
02 'use strict';
03 var deleteNonConfigurable = function () {
04 var obj = {};
05 Object.defineProperty(obj, "name", {
06 configurable: false
07 });
08 delete obj.name; //Will throw TypeError in Strict Mode
09 }
10 return deleteNonConfigurable;
11 }
12
13 wrapper()(); //TypeError (Strict Mode enforced)

Однако важно отметить, что строгий режим не применяется к нестрогим функциям, которые вызываются внутри тела строгой функции (либо потому, что они были переданы в качестве аргументов, либо вызываются с помощью call или apply)…

var test = function(fn) {
02 'use strict';
03 fn();
04 }
05
06 var deleteNonConfigurable = function () {
07 var obj = {};
08 Object.defineProperty(obj, "name", {
09 configurable: false
10 });
11 delete obj.name; //will throw TypeError in Strict Mode
12 }
13
14 test(deleteNonConfigurable); //no error (Strict Mode not enforced)

Почему я не могу запустить глобальный строгий режим в консоли браузера?

При запуске кода в firebug и других браузерных консолях первоначальное «строгое использование» (вне функции) не имеет никакого эффекта. Это связано с тем, что большинство участников консолей заключают весь код в вызов eval, поэтому ваше «строгое использование» больше не является первым утверждением. Частичный обходной путь заключается в том, чтобы обернуть ваш код в самопризывающуюся функцию, начинающуюся с «используйте строгий» (но даже тогда я обнаружил, что применение строгого режима в консоли довольно ненадежно — особенно при использовании инструментов разработчика webkit) — лучше тестировать свой код на веб-странице):

 

(function() {
2 "use strict";
3 var a;
4 var b;
5 function bar() {
6 x = 5; //Strict Mode will throw an error for implicit globals
7 }
8 bar(); //ReferenceError (Strict Mode is enforced)
9 })();

Что произойдет, если мой браузер не поддерживает строгий режим?

Ничего. Директива use strict — это просто строковое выражение, которое будет игнорироваться механизмами JavaScript, которые не поддерживают строгий режим. Это позволяет безопасно использовать кросс-браузерный синтаксис строгого режима, обеспечивая при этом встроенную прямую совместимость с браузерами, которые могут поддерживать строгий режим в будущем.

Каковы правила строгого режима?

Ограничения, определенные спецификацией строгого режима, охватывают поведение как во время загрузки, так и во время выполнения. Вот краткий обзор (каждое правило подробно описано на примере в следующем разделе):

Синтаксические ошибки

Во многих случаях строгий режим предотвращает даже неоднозначный или якобы вводящий в заблуждение код. Восьмеричные литералы, повторяющиеся имена свойств, неправильное использование delete и попытки сделать что-то хитрое с ключевыми словами eval и arguments, вызовет SyntaxError, как и любое использование оператора with.

Значение this

В строгом режиме значение этого параметра не будет автоматически принудительно привязано к объекту. Это, пожалуй, самая интересная часть строгого режима и та, которая может оказать наиболее значительное влияние на разработчиков. В частности, если первый аргумент для вызова или применения является нулевым или неопределенным, значение this вызванной функции не будет преобразовано в глобальный объект.

Неявные глобалы

Не многие люди будут спорить с этим. Создание неявных глобалов — почти всегда ошибка. в строгом режиме вы получите ReferenceError. Это научит тебя;-)

arguments.caller и arguments.callee

Эти полезные свойства не одобряются в строгом режиме. Определенно спорный. Менее используемые свойства function.arguments и function.caller также запрещены.

Нарушения определения свойства объекта

Попытка выполнить обновление свойства, когда определение его свойства определяет иначе, вызовет TypeError в строгом режиме.

Тесты

Вот полный исходный код моих тестов в строгом режиме. Каждому набору тестов предшествует комментарий, взятый непосредственно из тестируемой спецификации ECMAScript. Эта версия источника настроена для работы в «режиме консоли», то есть ее можно скопировать, вставить в консоль разработчика и запустить как есть. Тот же исходный прогон в «режиме HTML» используется для создания визуальной тестовой страницы, которую я представил в верхней части статьи. Этот источник с поддерживающими объектами находится в моем репозитории github . Я уверен, что сделал несколько ошибок — не стесняйтесь, дайте мне знать!

Заворачивать

Вопрос о том, делает ли ограничение доступа к языку лучших разработчиков, сомнителен, но давайте сохраним эту дискуссию в другой раз. В своей защите строгий режим является хорошим компромиссом между полным изменением языка (что привело бы к нарушению обратной совместимости) и бездействием (что вызвало бы недовольство у тех, кто настаивает на том, что более вопиющие части языка должны быть постепенно исключены). ). Если уж на то пошло, Strict Mode — это мясо и напитки для тех из нас, кто одержим нюансами этого захватывающего языка. Наслаждайтесь!

Дальнейшее чтение

ECMA-262, 5-е издание: строгий режим ECMAScript

Асен Божилов: Строгий тестер
Продуманный, тщательный набор тестов Строгого режима.

Юрий Зайцев (он же «kangax»): таблица совместимости ECMAScript 5 — поддержка строгого режима
Еще один хороший источник, часть основного справочника по совместимости от kangax (спасибо также kangax за последнюю минуту чата об этих тестах)