Что делает "use strict" в JavaScript, и каковы причины этого? Use strict javascript что это, ошибка ява скрипт Для чего используется строгий режим в js.

20.03.2024

(далее в статье Strict Mode). Strict Mode накладывает слой ограничений на JavaScript, он отгораживает вас от опасных частей языка (те части, которые есть исторически, но лучше чтобы их не было) и позволяет снизить вероятность ошибки.

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

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

Firefox 4 уже полностью поддерживает Strict Mode, а Chrome 11 практически полностью. Strict Mode уже не за горами - давайте изучим его подробнее!

Как включить Strict Mode? Если добавить "use strict" в начало вашего JavaScript кода, то Strict Mode будет применен для всего кода:
"use strict"; 012; //Восьмеричный литерал запрешен. Выбросит исключение SyntaxError в Strict Mode
В качестве альтернативы вы можете включить Strict Mode только в отдельной функции, добавив "use strict" в начало тела вашей функции:
012; //Нет ошибки (Strict Mode не включен глобально) function foo() { "use strict"; x=3; //Strict Mode выбросит исключение - запрещено неявно создавать глобальные переменные } foo(); //ReferenceError (Strict Mode включен для функции) Наследуют ли внутренние функции Strict Mode от внешних функций? Внутренняя функция, объявленная внутри внешней, в которой включен Strict Mode тоже будет иметь Strict Mode:
var wrapper = function(fn) { "use strict"; var deleteNonConfigurable = function () { var obj = {}; Object.defineProperty(obj, "name", { configurable: false }); delete obj.name; // Выбросит исключение TypeError в Strict Mode } return deleteNonConfigurable; } wrapper()(); //TypeError (Strict Mode включен)
Важно запомнить, что Strict Mode не распространяется на «нестрогие» (ориг. non-strict) функции, которые выполняются внутри строгой функции (или они отправлены в функцию в качестве аргументов или выполняются, используя call или apply):
var test = function(fn) { "use strict"; fn(); } var deleteNonConfigurable = function () { var obj = {}; Object.defineProperty(obj, "name", { configurable: false }); delete obj.name; // Выбросит исключение TypeError в Strict Mode } test(deleteNonConfigurable); //нет ошибки (Strict Mode не применялся) Почему я не могу включить Strict Mode в консоли моего браузера? Когда выполняешь код в консоли фаербага или в других консолях использование "use strict" вне функции не имеет силы. Это потому, что большинство консолей обрамляют ваш код в eval"ом, поэтому ваш "use strict" не является первым выражением. Это можно обойти, обрамив ваш код в замыкание (IIFE), в начало которого мы положим "use strict" (но, когда я тестировал такой способ включения Strict Mode я понял, что это довольно неудобно, особенно если работать в консоли webkit developer tools - лучше тестировать ваш код на странице):
(function() { "use strict"; var a; var b; function bar() { x = 5; //Strict Mode выбросит исключение за попытку создания глобальной переменной } bar(); // ReferenceError (Strict Mode включен) })(); Что произойдет если мой браузер не поддерживает Strict Mode? Ничего. Директива "use strict" это обычное строковое выражение, которое будет проигнорировано всеми движками JavaScript, которые не поддерживают Strict Mode. Это позволяет безопасно использовать синтаксис Strict Mode во всех браузерах без каких-либо опасений, в то время когда браузеры имеющие поддержку Strict Mode будут использовать его.Какие правила включены в Strict Mode? Правила определены в спецификации Strict Mode и включают в себя ограничения во время «компиляции» и интерпретации (выполнения скрипта). Это вводный обзор (каждое правило я описал с примерами в следующем параграфе): ecma262-5.com/ELS5_HTML.htm#Annex_C Синтаксические ошибки Syntax Errors В большинстве случаев Strict Mode предотвращает выполнение подозрительного или нелегального кода в процессе загрузки. Восьмеричные числа, дубли имен переменных, некорректное использование delete и попытки сделать что-нибудь этакие с eval и ключевым словом arguments, использование with приведет к исключению SyntaxError.Слово this В Strict Mode объект this не будет корректироваться. Это возможно самая интересная часть Strict Mode и самая тяжелая(шокирующая) для разработчиков. Все знают, что если первый аргумент call или apply - null или undefined, то значение this выполняемой функции будет преобразование в глобальный объект (для браузеров это window).Прямое создание глобальных переменных Не все согласятся с этим, но непрямое создание глобального объекта почти всегда является ошибкой. В Strict Mode вам выдадут красную карточку - ReferenceError.arguments.caller и arguments.callee Эти «полезные свойства» (от пер. никогда не применял их) запрещены в Strict Mode. Если вы используете их в вашем кода, то Strict Mode выбросит исключение.Объявление существующего имени объекта Когда вы создаете объект с двумя одинаковыми ключами, то Strict Mode выбросит исключение TypeError.Тесты Вот исходник моих Strict Mode тестов. Каждый набор тестов снабжен комментарием, ссылающемся на часть спецификации ECMAScript, которую он тестирует. Эта версия может быть выполнена в «режиме консоли». Т.е. вы можете скопировать тест, вставить в консоль и выполнить без изменений. Этот же код, работающий в режиме «HTML» я использовал для создания тестовой страницы, которую я представил вам в начале статьи. Этот исходник с дополнительными объектами в моем github репозитории . Я уверен, что там есть пара ошибок - не стесняйтесь присылать ошибки!

От переводчика: тут в статье шел огромный кусок кода, закинул его на pastebin

Заключение Запрещение обращение к некоторым возможностям языка для улучшения кода - вопрос спорный, давайте отложим эти споры. В защиту Strict Mode я хочу сказать, что это отличный компромисс между тотальными переменами (которые сломают обратную совместимость) и ничего не деланием (которое приведет к захламлению языка и научит разработчиков плохому). ECMA-262 5th Edition: The Strict Mode of ECMAScript
Asen Bozhilov: Strict tester
Таблица совместимости с ECMAScript 5, часть посвященная Strict mode . Это отличный источник, часть большой таблицы совместимости, разработанной Юрием Зайцевым (Juriy Zaytsev aka «kangax»)

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

Strict mode (в переводе с анг. - строгий режим) – это модель синтаксического анализа и выполнения JavaScript-кода, в которой используется более строгая проверка кода на ошибки и генерируются ошибки при небезопасных действиях.

Включение строгого режима

Чтобы включить строгий режим для всего сценария, добавьте в начало сценария следующую команду:

"use strict";

Хоть она и выглядит как строка, на самом деле это директива, переводящая JavaScript в строгий режим.

Строгий режим можно включить и для отдельной функции, добавив эту директиву в начало тела функции:

Function foo() { "use strict"; }

Директиву "use strict" можно указывать только в самом начале сценария или в самом начале функции. Это не означает, что она должна находиться в самой первой строке, но должна быть указана до других инструкций. Если директиву "use strict" указать не в начале, а в другом месте, она не будет работать:

"use strict"; // Правильное расположение a = 5; alert(a); b = 1; alert(b); a = 5; alert(a); "use strict"; // Неправильное расположение. Директива не будет работать b = 1; alert(b);

Выполнение JavaScript в строгом режиме
  • Все переменные перед их использованием должны быть объявлены. Попытка использовать переменную до объявления вызывает исключение.
  • При попытке присвоить значение необъявленной переменной возникает ошибка. Однако явное создание свойства глобального объекта и присвоение ему значения ошибку не вызывает: window.num = 10
  • В качестве идентификаторов нельзя использовать следующие слова: eval и arguments .
  • Попытка добавить новое свойство примитивному значению вызывает исключение.
  • Нельзя использовать инструкцию with .
  • Параметры функции не могут иметь одинаковые имена.
  • Параметры функции не синхронизируются со значениями объекта arguments .
  • Если функция вызывается как функция (а не как метод), ключевое слово this в качестве значения получает значение undefined , а не ссылку на глобальный объект.
  • Код, переданный функции eval() , выполняется в песочнице, это означает, что код по-прежнему может читать и изменять уже существующие переменные, однако переменные и функции, объявленные в переданном коде, наружу из песочницы не попадут: "use strict"; function foo() { var a = 10; eval("var x = 10; alert(x + a);"); alert(x); // Ошибка. Такой переменной не существует } foo();
  • Операндом оператора delete может быть только настраиваемое свойство объекта или элемент массива. Если операндом оператора delete является неквалифицированный идентификатор, такой как имя переменной, функции, параметр функции или имя ненастраиваемого свойства возбуждается ошибка.
  • В цепочке присваиваний нельзя использовать необъявленные переменные: var a = b = 5; // Ошибка. Необъявленная переменная (b)
  • Попытка присвоить значение свойству, недоступному для записи, или создание нового свойства в нерасширяемом объекте порождают исключение.
  • Обращение к свойствам arguments.caller и arguments.callee порождает исключение.
  • Функции, объявленные как FD внутри блока, находятся в блочной области видимости: { foo(); // 1 function foo () { alert(1); } } foo(); // Ошибка. Функция foo не объявлена.

(далее в статье Strict Mode). Strict Mode накладывает слой ограничений на JavaScript, он отгораживает вас от опасных частей языка (те части, которые есть исторически, но лучше чтобы их не было) и позволяет снизить вероятность ошибки.

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

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

Firefox 4 уже полностью поддерживает Strict Mode, а Chrome 11 практически полностью. Strict Mode уже не за горами - давайте изучим его подробнее!

Как включить Strict Mode? Если добавить "use strict" в начало вашего JavaScript кода, то Strict Mode будет применен для всего кода:
"use strict"; 012; //Восьмеричный литерал запрешен. Выбросит исключение SyntaxError в Strict Mode
В качестве альтернативы вы можете включить Strict Mode только в отдельной функции, добавив "use strict" в начало тела вашей функции:
012; //Нет ошибки (Strict Mode не включен глобально) function foo() { "use strict"; x=3; //Strict Mode выбросит исключение - запрещено неявно создавать глобальные переменные } foo(); //ReferenceError (Strict Mode включен для функции) Наследуют ли внутренние функции Strict Mode от внешних функций? Внутренняя функция, объявленная внутри внешней, в которой включен Strict Mode тоже будет иметь Strict Mode:
var wrapper = function(fn) { "use strict"; var deleteNonConfigurable = function () { var obj = {}; Object.defineProperty(obj, "name", { configurable: false }); delete obj.name; // Выбросит исключение TypeError в Strict Mode } return deleteNonConfigurable; } wrapper()(); //TypeError (Strict Mode включен)
Важно запомнить, что Strict Mode не распространяется на «нестрогие» (ориг. non-strict) функции, которые выполняются внутри строгой функции (или они отправлены в функцию в качестве аргументов или выполняются, используя call или apply):
var test = function(fn) { "use strict"; fn(); } var deleteNonConfigurable = function () { var obj = {}; Object.defineProperty(obj, "name", { configurable: false }); delete obj.name; // Выбросит исключение TypeError в Strict Mode } test(deleteNonConfigurable); //нет ошибки (Strict Mode не применялся) Почему я не могу включить Strict Mode в консоли моего браузера? Когда выполняешь код в консоли фаербага или в других консолях использование "use strict" вне функции не имеет силы. Это потому, что большинство консолей обрамляют ваш код в eval"ом, поэтому ваш "use strict" не является первым выражением. Это можно обойти, обрамив ваш код в замыкание (IIFE), в начало которого мы положим "use strict" (но, когда я тестировал такой способ включения Strict Mode я понял, что это довольно неудобно, особенно если работать в консоли webkit developer tools - лучше тестировать ваш код на странице):
(function() { "use strict"; var a; var b; function bar() { x = 5; //Strict Mode выбросит исключение за попытку создания глобальной переменной } bar(); // ReferenceError (Strict Mode включен) })(); Что произойдет если мой браузер не поддерживает Strict Mode? Ничего. Директива "use strict" это обычное строковое выражение, которое будет проигнорировано всеми движками JavaScript, которые не поддерживают Strict Mode. Это позволяет безопасно использовать синтаксис Strict Mode во всех браузерах без каких-либо опасений, в то время когда браузеры имеющие поддержку Strict Mode будут использовать его.Какие правила включены в Strict Mode? Правила определены в спецификации Strict Mode и включают в себя ограничения во время «компиляции» и интерпретации (выполнения скрипта). Это вводный обзор (каждое правило я описал с примерами в следующем параграфе): ecma262-5.com/ELS5_HTML.htm#Annex_C Синтаксические ошибки Syntax Errors В большинстве случаев Strict Mode предотвращает выполнение подозрительного или нелегального кода в процессе загрузки. Восьмеричные числа, дубли имен переменных, некорректное использование delete и попытки сделать что-нибудь этакие с eval и ключевым словом arguments, использование with приведет к исключению SyntaxError.Слово this В Strict Mode объект this не будет корректироваться. Это возможно самая интересная часть Strict Mode и самая тяжелая(шокирующая) для разработчиков. Все знают, что если первый аргумент call или apply - null или undefined, то значение this выполняемой функции будет преобразование в глобальный объект (для браузеров это window).Прямое создание глобальных переменных Не все согласятся с этим, но непрямое создание глобального объекта почти всегда является ошибкой. В Strict Mode вам выдадут красную карточку - ReferenceError.arguments.caller и arguments.callee Эти «полезные свойства» (от пер. никогда не применял их) запрещены в Strict Mode. Если вы используете их в вашем кода, то Strict Mode выбросит исключение.Объявление существующего имени объекта Когда вы создаете объект с двумя одинаковыми ключами, то Strict Mode выбросит исключение TypeError.Тесты Вот исходник моих Strict Mode тестов. Каждый набор тестов снабжен комментарием, ссылающемся на часть спецификации ECMAScript, которую он тестирует. Эта версия может быть выполнена в «режиме консоли». Т.е. вы можете скопировать тест, вставить в консоль и выполнить без изменений. Этот же код, работающий в режиме «HTML» я использовал для создания тестовой страницы, которую я представил вам в начале статьи. Этот исходник с дополнительными объектами в моем github репозитории . Я уверен, что там есть пара ошибок - не стесняйтесь присылать ошибки!

От переводчика: тут в статье шел огромный кусок кода, закинул его на pastebin

Заключение Запрещение обращение к некоторым возможностям языка для улучшения кода - вопрос спорный, давайте отложим эти споры. В защиту Strict Mode я хочу сказать, что это отличный компромисс между тотальными переменами (которые сломают обратную совместимость) и ничего не деланием (которое приведет к захламлению языка и научит разработчиков плохому). ECMA-262 5th Edition: The Strict Mode of ECMAScript
Asen Bozhilov: Strict tester
Таблица совместимости с ECMAScript 5, часть посвященная Strict mode . Это отличный источник, часть большой таблицы совместимости, разработанной Юрием Зайцевым (Juriy Zaytsev aka «kangax»)

От переводчика. Strict Mode поддерживают практически половина всех браузеров, кроме своих прекрасных ограничений и иммунитету к распространенным ошибкам Strict Mode дает и другие преимущества (статья mraleph). Скоро неиспользование Strict Mode станет плохим тоном (аналогично requestAnimationFrame vs setTimeout). Сейчас самое время начать эксперименты!

Sometimes you"ll see the default, non-strict mode referred to as " " . This isn"t an official term, but be aware of it, just in case.

JavaScript"s strict mode, introduced in ECMAScript 5, is a way to opt in to a restricted variant of JavaScript, thereby implicitly opting-out of " ". Strict mode isn"t just a subset: it intentionally has different semantics from normal code. Browsers not supporting strict mode will run strict mode code with different behavior from browsers that do, so don"t rely on strict mode without feature-testing for support for the relevant aspects of strict mode. Strict mode code and non-strict mode code can coexist, so scripts can opt into strict mode incrementally.

Strict mode makes several changes to normal JavaScript semantics:

  • Eliminates some JavaScript silent errors by changing them to throw errors.
  • Fixes mistakes that make it difficult for JavaScript engines to perform optimizations: strict mode code can sometimes be made to run faster than identical code that"s not strict mode.
  • Prohibits some syntax likely to be defined in future versions of ECMAScript.
  • (function() { "use strict"; false.true = ""; // TypeError (14).sailing = "home"; // TypeError "with".you = "far away"; // TypeError })(); Simplifying variable uses

    Strict mode simplifies how variable names map to particular variable definitions in the code. Many compiler optimizations rely on the ability to say that variable X is stored in that location: this is critical to fully optimizing JavaScript code. JavaScript sometimes makes this basic mapping of name to variable definition in the code impossible to perform until runtime. Strict mode removes most cases where this happens, so the compiler can better optimize strict mode code.

    First, strict mode prohibits with . The problem with with is that any name inside the block might map either to a property of the object passed to it, or to a variable in surrounding (or even global) scope, at runtime: it"s impossible to know which beforehand. Strict mode makes with a syntax error, so there"s no chance for a name in a with to refer to an unknown location at runtime:

    "use strict"; var x = 17; with (obj) { // !!! syntax error // If this weren"t strict mode, would this be var x, or // would it instead be obj.x? It"s impossible in general // to say without running the code, so the name can"t be // optimized. x; }

    The simple alternative of assigning the object to a short name variable, then accessing the corresponding property on that variable, stands ready to replace with .

    Second, . In normal code eval("var x;") introduces a variable x into the surrounding function or the global scope. This means that, in general, in a function containing a call to eval every name not referring to an argument or local variable must be mapped to a particular definition at runtime (because that eval might have introduced a new variable that would hide the outer variable). In strict mode eval creates variables only for the code being evaluated, so eval can"t affect whether a name refers to an outer variable or some local variable:

    Var x = 17; var evalX = eval(""use strict"; var x = 42; x;"); console.assert(x === 17); console.assert(evalX === 42);

    If the function eval is invoked by an expression of the form eval(...) in strict mode code, the code will be evaluated as strict mode code. The code may explicitly invoke strict mode, but it"s unnecessary to do so.

    Function strict1(str) { "use strict"; return eval(str); // str will be treated as strict mode code } function strict2(f, str) { "use strict"; return f(str); // not eval(...): str is strict if and only // if it invokes strict mode } function nonstrict(str) { return eval(str); // str is strict if and only // if it invokes strict mode } strict1(""Strict mode code!""); strict1(""use strict"; "Strict mode code!""); strict2(eval, ""Non-strict code.""); strict2(eval, ""use strict"; "Strict mode code!""); nonstrict(""Non-strict code.""); nonstrict(""use strict"; "Strict mode code!"");

    Thus names in strict mode eval code behave identically to names in strict mode code not being evaluated as the result of eval .

    Third, strict mode forbids deleting plain names. delete name in strict mode is a syntax error:

    "use strict"; var x; delete x; // !!! syntax error eval("var y; delete y;"); // !!! syntax error

    Making eval and arguments simpler

    Strict mode makes arguments and eval less bizarrely magical. Both involve a considerable amount of magical behavior in normal code: eval to add or remove bindings and to change binding values, and arguments by its indexed properties aliasing named arguments. Strict mode makes great strides toward treating eval and arguments as keywords, although full fixes will not come until a future edition of ECMAScript.

    First, the names eval and arguments can"t be bound or assigned in language syntax. All these attempts to do so are syntax errors:

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

    Second, strict mode code doesn"t alias properties of arguments objects created within it. In normal code within a function whose first argument is arg , setting arg also sets arguments , and vice versa (unless no arguments were provided or arguments is deleted). arguments objects for strict mode functions store the original arguments when the function was invoked. arguments[i] does not track the value of the corresponding named argument, nor does a named argument track the value in the corresponding arguments[i] .

    Function f(a) { "use strict"; a = 42; return ; } var pair = f(17); console.assert(pair === 42); console.assert(pair === 17);

    Third, arguments.callee is no longer supported. In normal code arguments.callee refers to the enclosing function. This use case is weak: simply name the enclosing function! Moreover, arguments.callee substantially hinders optimizations like inlining functions, because it must be made possible to provide a reference to the un-inlined function if arguments.callee is accessed. arguments.callee for strict mode functions is a non-deletable property which throws an error when set or retrieved:

    "use strict"; var f = function() { return arguments.callee; }; f(); // throws a TypeError

    "Securing" JavaScript

    Strict mode makes it easier to write "secure" JavaScript. Some websites now provide ways for users to write JavaScript which will be run by the website on behalf of other users . JavaScript in browsers can access the user"s private information, so such JavaScript must be partially transformed before it is run, to censor access to forbidden functionality. JavaScript"s flexibility makes it effectively impossible to do this without many runtime checks. Certain language functions are so pervasive that performing runtime checks has a considerable performance cost. A few strict mode tweaks, plus requiring that user-submitted JavaScript be strict mode code and that it be invoked in a certain manner, substantially reduce the need for those runtime checks.

    First, the value passed as this to a function in strict mode is not forced into being an object (a.k.a. "boxed"). For a normal function, this is always an object: either the provided object if called with an object-valued this ; the value, boxed, if called with a Boolean, string, or number this ; or the global object if called with an undefined or null this . (Use call , apply , or bind to specify a particular this .) Not only is automatic boxing a performance cost, but exposing the global object in browsers is a security hazard because the global object provides access to functionality that "secure" JavaScript environments must restrict. Thus for a strict mode function, the specified this is not boxed into an object, and if unspecified, this will be undefined:

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

    That means, among other things, that in browsers it"s no longer possible to reference the window object through this inside a strict mode function.

    Second, in strict mode it"s no longer possible to "walk" the JavaScript stack via commonly-implemented extensions to ECMAScript. In normal code with these extensions, when a function fun is in the middle of being called, fun.caller is the function that most recently called fun , and fun.arguments is the arguments for that invocation of fun . Both extensions are problematic for "secure" JavaScript because they allow "secured" code to access "privileged" functions and their (potentially unsecured) arguments. If fun is in strict mode, both fun.caller and fun.arguments are non-deletable properties which throw when set or retrieved:

    Function restricted() { "use strict"; restricted.caller; // throws a TypeError restricted.arguments; // throws a TypeError } function privilegedInvoker() { return restricted(); } privilegedInvoker();

    Third, arguments for strict mode functions no longer provide access to the corresponding function call"s variables. In some old ECMAScript implementations arguments.caller was an object whose properties aliased variables in that function. This is a security hazard because it breaks the ability to hide privileged values via function abstraction; it also precludes most optimizations. For these reasons no recent browsers implement it. Yet because of its historical functionality, arguments.caller for a strict mode function is also a non-deletable property which throws when set or retrieved:

    "use strict"; function fun(a, b) { "use strict"; var v = 12; return arguments.caller; // throws a TypeError } fun(1, 2); // doesn"t expose v (or a or b)

    Paving the way for future ECMAScript versions

    Future ECMAScript versions will likely introduce new syntax, and strict mode in ECMAScript 5 applies some restrictions to ease the transition. It will be easier to make some changes if the foundations of those changes are prohibited in strict mode.

    First, in strict mode, a short list of identifiers become reserved keywords. These words are implements , interface , let , package , private , protected , public , static , and yield . In strict mode, then, you can"t name or use variables or arguments with these names.

    Function package(protected) { // !!! "use strict"; var implements; // !!! interface: // !!! while (true) { break interface; // !!! } function private() { } // !!! } function fun(static) { "use strict"; } // !!!

    Two Mozilla-specific caveats: First, if your code is JavaScript 1.7 or greater (for example in chrome code or when using the right ) and is strict mode code, let and yield have the functionality they"ve had since those keywords were first introduced. But strict mode code on the web, loaded with or ... , won"t be able to use let / yield as identifiers. Second, while ES5 unconditionally reserves the words class , enum , export , extends , import , and super , before Firefox 5 Mozilla reserved them only in strict mode.

    Second, . In normal mode in browsers, function statements are permitted "everywhere". This is not part of ES5 (or even ES3)! It"s an extension with incompatible semantics in different browsers. Note that function statements outside top level are permitted in ES2015.

    "use strict"; 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 }

    This prohibition isn"t strict mode proper because such function statements are an extension of basic ES5. But it is the recommendation of the ECMAScript committee, and browsers will implement it.

    Strict mode in browsers

    The major browsers now implement strict mode. However, don"t blindly depend on it since there still are numerous Browser versions used in the wild that only have partial support for strict mode or do not support it at all (e.g. Internet Explorer below version 10!). Strict mode changes semantics. Relying on those changes will cause mistakes and errors in browsers which don"t implement strict mode. Exercise caution in using strict mode, and back up reliance on strict mode with feature tests that check whether relevant parts of strict mode are implemented. Finally, make sure to test your code in browsers that do and don"t support strict mode . If you test only in browsers that don"t support strict mode, you"re very likely to have problems in browsers that do, and vice versa.

    Specifications Specification Status Comment
    ECMAScript 5.1 (ECMA-262)
    Standard Initial definition. See also:
    ECMAScript 2015 (6th Edition, ECMA-262)
    The definition of "Strict Mode Code" in that specification.
    Standard Strict mode restriction and exceptions
    ECMAScript Latest Draft (ECMA-262)
    The definition of "Strict Mode Code" in that specification.
    Draft

    Недавно я запустил код моего кода JavaScript через Crockford JSLint , и он дал следующую ошибку:

    Problem at line 1 character 1: Missing "use strict" statement.

    Выполняя некоторые поиски, я понял, что некоторые люди добавляют "use strict"; в свой код JavaScript. Как только я добавил выражение, ошибка перестала появляться. К сожалению, Google не раскрыл большую часть истории этого оператора строки. Конечно, это должно быть связано с тем, как JavaScript интерпретируется браузером, но я не знаю, каким будет эффект.

    Итак, что такое "use strict"; все о том, что это подразумевает, и все еще актуально?

    Любой из текущих браузеров реагирует на "use strict"; строка или это для будущего использования?

    30 ответов

    Эта статья о строгом режиме Javascript может вас заинтересовать: Джон Резиг - ECMAScript 5 Strict Mode, JSON и другие

    Процитирую некоторые интересные части:

    Строгий режим - это новая функция в ECMAScript 5, позволяющая поместить программу или функцию в "строгий" рабочий контекст. Этот строгий контекст предотвращает выполнение определенных действий и вызывает больше исключений.

    Строгий режим выручает несколькими способами:

    • Он ловит некоторые распространенные ошибки кодирования, создавая исключения.
    • Он предотвращает или выдает ошибки, когда предпринимаются относительно "небезопасные" действия (например, получение доступа к глобальному объекту).
    • Это отключает функции, которые сбивают с толку или плохо продуманы.

    Также обратите внимание, что вы можете применить "строгий режим" ко всему файлу... Или вы можете использовать его только для определенной функции (все еще цитируя статью Джона Резига):

    // Non-strict code... (function(){ "use strict"; // Define your library strictly... })(); // Non-strict code...

    Что может быть полезно, если вам нужно смешать старый и новый код;-)

    Итак, я предполагаю, что это немного похоже на "use strict" вы можете использовать в Perl (отсюда и название?): Оно помогает вам делать меньше ошибок, обнаруживая больше вещей, которые могут привести к поломкам.

    Это новая особенность ECMAScript 5. Джон Ресиг написал хорошее резюме .

    Это просто строка, которую вы помещаете в свои файлы JavaScript (либо вверху вашего файла, либо внутри функции), которая выглядит так:

    "use strict";

    Включение этого кода теперь не должно вызывать проблем с текущими браузерами, поскольку это просто строка. Это может вызвать проблемы с вашим кодом в будущем, если ваш код нарушает прагму. Например, если у вас в настоящее время есть foo = "bar" не определяя сначала foo , ваш код начнет сбой... что, на мой взгляд, хорошо.

    Утверждение "use strict"; инструктирует браузер использовать режим Strict, который является уменьшенным и более безопасным набором функций JavaScript.

    Список функций (неисчерпывающий)

    Запрещает глобальные переменные. (Убирает отсутствующие объявления var и опечатки в именах переменных)

    Бесшумные неудачные задания будут вызывать ошибку в строгом режиме (назначая NaN = 5;)

    Попытки удалить отказоустойчивые свойства будут вызывать (delete Object.prototype)

    Требует, чтобы все имена свойств в объектном литерале были уникальными (var x = {x1: "1", x1: "2"})

    Имена функциональных параметров должны быть уникальными (function sum (x, x) {...})

    Forbids - восьмеричный синтаксис (var x = 023; некоторые разработчики ошибочно полагают, что предыдущий нуль не делает ничего, чтобы изменить число.)

    Запрещающий with ключевым словом

    eval в строгом режиме не вводит новые переменные

    Запретить удаление простых имен (delete x;)

    Запрет привязки или присвоения имен eval и arguments в любой форме

    Строгий режим не поддерживает свойства объекта arguments с формальными параметрами. (т.е. в function sum (a,b) { return arguments + b;} Это работает, потому что arguments связаны с a и т.д.)

    arguments.callee не поддерживается

    Если люди обеспокоены use strict возможно, стоит проверить эту статью:

    Слово предостережения, все, что вы программируете с жесткой зарядкой: применение "use strict" к существующему коду может быть опасным! Эта вещь не какая-то приятная, счастливая наклейка, которую вы можете похлопать по коду, чтобы сделать ее "лучше". При "use strict" правильной "use strict" прагмы браузер внезапно выбрасывает исключения в случайных местах, которые он никогда не бросал раньше, просто потому, что в этом месте вы делаете то, что позволяет по умолчанию/свободно JavaScript, но строгий JavaScript не нравится! У вас могут быть нарушения строгости, скрывающиеся в редко используемых вызовах вашего кода, которые будут генерировать исключение только тогда, когда они в конечном итоге будут запущены - скажем, в производственной среде, которую используют ваши платежные клиенты!

    Если вы собираетесь сделать решительный шаг, рекомендуется применять "use strict" наряду с комплексными модульными тестами и строго сконфигурированной задачей сборки JSHint, которая даст вам уверенность в том, что нет темного угла вашего модуля, который взорвется ужасно, потому что вы включили строгий режим. Или, эй, вот еще один вариант: просто не добавляйте "use strict" к любому из ваших устаревших кодов, это, вероятно, безопаснее, честно. ОПРЕДЕЛЕННО НЕ добавляйте "use strict" для любых модулей, которые вы не владеете или не поддерживаете, например, сторонние модули.

    Я думаю, что даже если это смертоносный живот в клетке, "use strict" может быть хорошим, но вы должны сделать это правильно. Лучшее время, чтобы идти строгим, - это когда ваш проект является новым, и вы начинаете с нуля. Настройте JSHint/JSLint со всеми предупреждениями и параметрами, сложенными так же сильно, как ваша команда может вздрагивать, получить хорошую систему сборки/тестирования/утверждения, которую можно настроить как Grunt+Karma+Chai , и только THEN начнет маркировать все ваши новые модули как "use strict" . Будьте готовы вылечить множество ошибок и предупреждений. Убедитесь, что все понимают гравитацию, настроив сборку на FAIL, если JSHint/JSLint вызывает какие-либо нарушения.

    Мой проект не был новым проектом, когда я принял "use strict" . В результате моя IDE полна красных отметок, потому что у меня нет "use strict" на половине моих модулей, и JSHint жалуется на это. Это напоминание мне о том, какой рефакторинг я должен делать в будущем. Моя цель - быть красной отметкой бесплатно из-за всех моих отсутствующих "use strict" заявлений, но это уже много лет.

    В моем новом приложении JavaScript: Абсолютно! Строгий режим можно использовать в качестве осведомителя, когда вы делаете что-то глупое с вашим кодом.

    В моем существующем JavaScript-коде: Наверное, нет! Если в вашем существующем JavaScript-коде есть инструкции, которые запрещены в строгом режиме, приложение просто сломается. Если вам нужен строгий режим, вы должны быть готовы отлаживать и исправлять существующий код. Вот почему использование "use strict"; не делает ваш код лучше.

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

    Вставить "use strict"; в верхней части вашего скрипта:

    // File: myscript.js "use strict"; var a = 2; ....

    Обратите внимание, что все в файле myscript.js будет интерпретироваться в строгом режиме.

    Или вставьте "use strict"; утверждение сверху вашего тела функции:

    Function doSomething() { "use strict"; ... }

    Все в лексическом объеме функции doSomething будет интерпретироваться в строгом режиме. Здесь важна лексическая область слова. См. Этот ответ для лучшего объяснения.

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

    Я настоятельно рекомендую всем разработчикам начать использовать строгий режим. Есть достаточно браузеров, поддерживающих его, что строгий режим законно поможет спасти нас от ошибок, которые мы даже не знали, были в вашем коде.

    По-видимому, на начальном этапе будут ошибки, с которыми мы никогда не сталкивались раньше. Чтобы получить полную выгоду, нам нужно провести надлежащее тестирование после перехода в строгий режим, чтобы убедиться, что мы все поймали. Определенно, мы просто не use strict в нашем коде и считаем, что ошибок нет. Таким образом, оттока заключается в том, что его время для начала использования этой невероятно полезной языковой функции для написания лучшего кода.

    Например,

    Var person = { name: "xyz", position: "abc", fullname: function () { "use strict"; return this.name; } };

    Я хотел бы предложить несколько более обоснованный ответ, дополняющий другие ответы. Я надеялся отредактировать самый популярный ответ, но не смог. Я старался сделать это как можно более полным и полным.

    Для получения дополнительной информации вы можете обратиться к документации MDN .

    "use strict" директиву, введенную в ECMAScript 5.

    Директивы похожи на утверждения, но разные.

    • use strict не содержит ключевых слов: директива - это простой оператор выражения, который состоит из специального строкового литерала (в одиночных или двойных кавычках). Механизмы JavaScript, которые не реализуют ECMAScript 5, просто видят выражение без побочных эффектов. Ожидается, что будущие версии стандартов ECMAScript внедрят use в качестве реального ключевого слова; Таким образом, кавычки станут устаревшими.
    • use strict может использоваться только в начале скрипта или функции, т.е. должно предшествовать любому другому (реальному) утверждению. Это не должно быть первой инструкцией в скрипте функции: ей могут предшествовать другие выражения операторов, которые состоят из строковых литералов (и реализации JavaScript могут рассматриваться как директивы, специфичные для реализации). Строковые литералы, которые следуют за первым реальным оператором (в скрипте или функции), являются простыми выражениями. Интерпретаторы не должны интерпретировать их как директивы, и они не имеют никакого эффекта.

    use strict директива use strict указывает, что следующий код (в скрипте или функции) является строгим кодом. Код на самом высоком уровне скрипта (код, который не находится в функции) считается строгим кодом, когда скрипт содержит use strict директиву use strict . Содержание функции считается строгим кодом, когда сама функция определена в строгом коде или когда функция содержит use strict директиву use strict . Код, передаваемый методу eval() считается строгим кодом, когда eval() вызывается из строкового кода или содержит use strict директиву use strict .

    Строгий режим ECMAScript 5 является ограниченным подмножеством языка JavaScript, что устраняет соответствующие недостатки языка и обеспечивает более строгую проверку ошибок и повышенную безопасность. Ниже перечислены различия между строгим режимом и нормальным режимом (из которых особенно важны первые три):

    • Вы не можете использовать его with -statement в строгом режиме.
    • В строгом режиме все переменные должны быть объявлены: если вы присваиваете значение идентификатору, который не был объявлен как переменная, функция, параметр функции, параметр catch-clause или свойство глобального Object , тогда вы получите ReferenceError . В нормальном режиме идентификатор объявляется неявно как глобальная переменная (как свойство глобального Object)
    • В строгом режиме ключевое слово this имеет значение undefined функции, которые были вызываться как функции (а не как методы). (В нормальном режиме this всегда указывает на глобальный Object). Это различие можно использовать для проверки, поддерживает ли реализация строгий режим:
    var hasStrictMode = (function() { "use strict"; return this===undefined }());

      Также, когда функция вызывается с call() или apply в строгом режиме, this точно значение первого аргумента call() или apply() . (В нормальном режиме null и undefined заменяются глобальным Object а значения, которые не являются объектами, преобразуются в объекты.)

      В строгом режиме вы получите TypeError , когда вы пытаетесь назначить свойства readonly или определить новые свойства для не растяжимого объекта. (В обычном режиме оба просто обходятся без сообщения об ошибке.)

    • В строгом режиме при передаче кода в eval() вы не можете объявлять или определять переменные или функции в области вызывающего (как это можно сделать в обычном режиме). Вместо этого для eval() создается новая область, и переменные и функции находятся в пределах этой области. Эта область уничтожается после того, как eval() завершает выполнение.
    • В строгом режиме аргумент-объект функции содержит статическую копию значений, которые передаются этой функции. В нормальном режиме аргумент-объект имеет несколько "магическое" поведение: элементы массива и именованные функциональные параметры ссылаются на одно и то же значение.
    • В строгом режиме вы получите SyntaxError когда за оператором delete следует неквалифицированный идентификатор (переменная, функция или параметр функции). В нормальном режиме выражение delete ничего не сделает и будет оценено как false .
    • В строгом режиме вы получите TypeError при попытке удалить неконфигурируемое свойство. (В обычном режиме попытка просто терпит неудачу, а выражение delete - false).
    • В строгом режиме это считается синтаксической ошибкой при попытке определить несколько свойств с тем же именем для литерала объекта. (В нормальном режиме ошибки нет.)
    • В строгом режиме это считается синтаксической ошибкой, когда объявление функции имеет несколько параметров с тем же именем. (В нормальном режиме ошибки нет.)
    • В строгом режиме не допускаются восьмеричные литералы (это литералы, начинающиеся с 0x . (В нормальном режиме некоторые реализации позволяют делать восьмеричные литералы).
    • В строгом режиме идентификаторы eval и arguments обрабатываются как ключевые слова. Вы не можете изменить их значение, не можете присвоить им значение, и вы не можете использовать их в качестве имен для переменных, функций, параметров функций или идентификаторов блока catch.
    • В строгом режиме больше ограничений на возможности проверки стека вызовов. arguments.caller и arguments.callee вызывают TypeError в функции в строгом режиме. Кроме того, некоторые свойства caller- и аргументы функций в строгом режиме вызывают TypeError при попытке их прочитать.

    Мои два цента:

    Одна из целей строгого режима - обеспечить более быструю отладку проблем. Это помогает разработчикам, бросая исключение, когда происходят некоторые неправильные вещи, которые могут вызвать тихое и странное поведение вашей веб-страницы. В тот момент, когда мы используем use strict , код выкидывает ошибки, которые помогают разработчику исправлять его заранее.

    Немного важных вещей, которые я узнал после use strict:

    Предотвращает глобальную декларацию переменных:

    Var tree1Data = { name: "Banana Tree",age: 100,leafCount: 100000}; function Tree(typeOfTree) { var age; var leafCount; age = typeOfTree.age; leafCount = typeOfTree.leafCount; nameoftree = typeOfTree.name; }; var tree1 = new Tree(tree1Data); console.log(window);

    Теперь этот код создает nameoftree в глобальной области видимости, доступ к которому можно получить с помощью window.nameoftree . Когда мы реализуем use strict использование кода, код будет вызывать ошибку.

    Uncaught ReferenceError: nameoftree не определен

    Исключает with утверждением:

    with утверждениями не могут быть уменьшены с помощью таких инструментов, как uglify-js . Они также устарели и удалены из будущих версий JavaScript.

    Предотвращает дублирование:

    Когда у нас есть свойство duplicate, оно выдает исключение

    Uncaught SyntaxError: Дублирование свойства данных в объектном литерале не допускается в строгом режиме

    "use strict"; var tree1Data = { name: "Banana Tree", age: 100, leafCount: 100000, name:"Banana Tree" };

    Есть еще несколько, но мне нужно больше узнать об этом.

    Если вы используете браузер, выпущенный в прошлом году или около того, он, скорее всего, поддерживает режим JavaScript Strict. Только старые браузеры до того, как ECMAScript 5 стал текущим стандартом, не поддерживают его.

    Кавычки вокруг команды удостоверяются, что код по-прежнему будет работать и в старых браузерах (хотя вещи, которые генерируют синтаксическую ошибку в строгом режиме, как правило, просто приводят к тому, что скрипт будет работать некорректно в некоторых труднодоступных браузерах).

    При добавлении "use strict"; , следующие случаи будут бросать SyntaxError перед выполнением скрипта: