Что делает «использование строгого» в JavaScript, и каковы причины этого? - PullRequest
7174 голосов
/ 26 августа 2009

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

Проблема в строке 1, символ 1: отсутствует выражение "использовать строгий".

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

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

Отвечает ли текущий браузер строке "use strict"; или она предназначена для использования в будущем?

Ответы [ 26 ]

4710 голосов
/ 26 августа 2009

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

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

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

И

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

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

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

// Non-strict code...

(function(){
  "use strict";

  // Define your library strictly...
})();

// Non-strict code... 

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

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

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

1188 голосов
/ 26 августа 2009

Это новая функция ECMAScript 5. Джон Резиг написал хорошее резюме этого.

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

"use strict";

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

602 голосов
/ 25 ноября 2014

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

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

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

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

  3. Попытки удалить неотменяемые свойства приведут к (delete Object.prototype)

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

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

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

  7. Запрещает ключевое слово with

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

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

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

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

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

[Ref: Строгий режим , Сеть разработчиков Mozilla ]

392 голосов
/ 16 июля 2012

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

ECMAScript 5 Поддержка "Строгого режима" в браузерах. Что это значит?
NovoGeek.com - блог Кришны

В нем говорится о поддержке браузера, но, что более важно, о том, как безопасно с ней обращаться:

function isStrictMode(){
    return !this;
} 
/*
   returns false, since 'this' refers to global object and 
   '!this' becomes false
*/

function isStrictMode(){   
    "use strict";
    return !this;
} 
/* 
   returns true, since in strict mode the keyword 'this'
   does not refer to global object, unlike traditional JS. 
   So here, 'this' is 'undefined' and '!this' becomes true.
*/
198 голосов
/ 03 марта 2014

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

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

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

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

151 голосов
/ 29 января 2016

Использование 'use strict'; не делает ваш код внезапно лучше.

Строгий режим JavaScript является функцией ECMAScript 5 . Вы можете включить строгий режим, объявив это в верхней части скрипта / функции.

'use strict';

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

Рассмотрим этот пример:

var a = 365;
var b = 030;

Стремясь выстроить числовые литералы, разработчик непреднамеренно инициализировал переменную b с восьмеричным литералом. В нестрогом режиме это будет интерпретироваться как числовой литерал со значением 24 (в базе 10). Однако строгий режим выдаст ошибку.

Для неисчерпывающего списка специальностей в строгом режиме см. этот ответ .


Где я должен использовать 'use strict';?

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

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


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

  1. Вставьте оператор 'use strict'; поверх вашего скрипта:

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

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

  2. Или вставьте оператор 'use strict'; поверх тела вашей функции:

    function doSomething() {
        'use strict';
        ...
    }
    

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


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

Я нашел хорошую статью , описывающую несколько вещей, которые запрещены в строгом режиме (обратите внимание, что это не эксклюзивный список):

Область

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

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

Одним из преимуществ строгого кода является то, что такие инструменты, как YUI Compressor может лучше выполнять работу при обработке.

подразумеваемые глобальные переменные

JavaScript подразумевает глобальные переменные. Если Вы явно не объявляете переменную, глобальная переменная неявно заявлено для вас. Это облегчает программирование для новички, потому что они могут пренебречь некоторыми из их основной уборки хозяйственные работы. Но это делает управление большими программами намного более сложно и это значительно снижает надежность. Так что в строгом режим, подразумеваемые глобальные переменные больше не создаются. Вам следует явно объявите все ваши переменные.

Глобальная утечка

Существует ряд ситуаций, которые могут вызвать this быть привязанным к глобальному объекту. Например, если вы забудете предоставить префикс new при вызове функции конструктора, this конструктора будет неожиданно связан с глобальным объектом, поэтому вместо инициализации нового объекта, он будет молча вмешательство в глобальные переменные. В этих ситуациях строгий режим будет вместо этого свяжите this с undefined, что заставит конструктор вместо этого выведите исключение, позволяющее обнаружить ошибку рано.

Шумный отказ

JavaScript всегда имел свойства только для чтения, но вы не мог создать их самостоятельно до ES5's Object.createProperty функция раскрыла эту возможность. Если вы пытались присвоить значение для свойства только для чтения, он молча потерпит неудачу. Назначение будет не изменяйте значение свойства, но ваша программа будет работать как хотя это было. Это угроза целостности, которая может привести к тому, что программы перейти в противоречивое состояние. В строгом режиме пытается изменить свойство только для чтения вызовет исключение.

восьмиштырьковый

восьмеричное (или базовое 8) представление чисел было чрезвычайно полезно при программировании на уровне машин на машинах, чье слово размеры были кратны 3. Вам нужно восьмеричное при работе с CDC 6600 мэйнфреймов, размер слова которых составлял 60 бит. Если бы вы могли читать восьмеричное, вы можете посмотреть на слово как 20 цифр. Две цифры представлены код операции и одна цифра идентифицировали один из 8 регистров. В течение медленный переход от машинных кодов к языкам высокого уровня, это было считается полезным для предоставления восьмеричных форм в языках программирования.

В Си крайне неудачное представление восьмеричности было выбрано: ведущий ноль. Таким образом, в C 0100 означает 64, а не 100, а 08 является ошибка, а не 8. Еще более, к сожалению, этот анахронизм был скопированы почти на все современные языки, включая JavaScript, где он используется только для создания ошибок. У него нет другой цели. Так в строгий режим, восьмеричные формы больше не разрешены.

и так далее

Псевдомассив аргументов становится немного больше массив как в ES5. В строгом режиме он теряет callee и caller свойства. Это позволяет передать ваш arguments ненадежным код, не отказываясь от большого количества конфиденциального контекста. Так же arguments свойство функций исключено.

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


Зарезервированные слова для будущих версий JavaScript

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

implements, interface, let, package, private, protected, public, static и yield


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

131 голосов
/ 05 июля 2013

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

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

Например,

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

JSLint - отладчик, написанный Дугласом Крокфордом. Просто вставьте ваш скрипт, и он быстро отыщет любые заметные проблемы и ошибки в вашем коде.

92 голосов
/ 15 мая 2015

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

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

"use strict" директива, введенная в ECMAScript 5.

Директивы похожи на утверждения, но отличаются.

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

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

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

  • Вы не можете использовать with заявление в строгом режиме.
  • В строгом режиме все переменные должны быть объявлены: если вы присвоите значение идентификатору, который не был объявлен как переменная, функция, параметр функции, параметр 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, когда вы попытаетесь присвоить свойства только для чтения или определить новые свойства для нерасширяемого объекта. (В обычном режиме оба просто терпят неудачу без сообщения об ошибке.)

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

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

Одна из целей строгого режима - обеспечить более быструю отладку проблем. Это помогает разработчикам, создавая исключения, когда происходят определенные неправильные вещи, которые могут вызвать тихое и странное поведение вашей веб-страницы. В тот момент, когда мы используем 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 не определено

Sample

Исключает оператор with:

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

Sample

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

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

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

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

Есть еще немного, но мне нужно получить больше знаний об этом.

59 голосов
/ 10 марта 2012

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

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

...