Что именно делает строгий режим JavaScript в отношении неявных глобальных объявлений?

Из статьи MDN о строгом режиме:

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

'use strict';
                       // Assuming a global variable mistypedVariable exists
mistypeVariable = 17;  // this line throws a ReferenceError due to the 
                       // misspelling of variable

Что это значит? Обнаруживает ли механизм, существует ли уже переменная с таким именем (?!), или строгий режим просто запрещает объявление глобальных переменных за пределами глобальной области видимости?

Приведенная выше цитата, кажется, намекает на первую возможность, но это кажется... странным?


person Community    schedule 20.12.2018    source источник
comment
Я думаю, что ваше замешательство связано с идеей, что mistypeVariable = 17; является правильным объявлением. Это было бы в неаккуратном режиме, но в строгом режиме это не создание переменной, поэтому, если у вас уже не было let или var для нее, это ошибка.   -  person trincot    schedule 20.12.2018
comment
Я не уверен, что понимаю вопрос. В строгом режиме это вызовет ошибку. В неаккуратном режиме он неявно создаст глобальную переменную с именем mistypeVariable со значением 17, что почти всегда гораздо менее полезно. (Даже если эта глобальная переменная никогда не встанет у вас на пути, что, вероятно, и не произойдет, вы не узнаете об ошибке до тех пор, пока не попытаетесь выяснить какую-то странную ошибку.)   -  person Robin Zigmond    schedule 20.12.2018
comment
@trincot (1), так как же объявить глобальные переменные строгими? или вообще строго запрещает глобалы? (2) Согласно моей цитате: Предполагая, что глобальная переменная mistypedVariable существует, эта строка выдает ReferenceError — акцент мой. Насколько я понимаю, JS-движок должен проверять похожие имена?   -  person    schedule 20.12.2018
comment
@RobinZigmond Да, но предотвращает ли строгий режим неявные объявления только если переменные с аналогичными именами уже существуют? Эта часть, которую я выделил курсивом, меня смущает   -  person    schedule 20.12.2018
comment
@gazkam, конечно, вы можете создавать глобальные переменные в строгом режиме, но только объявляя их (с var, let или const) в глобальной области видимости. Именно так вы должны их делать в любом случае (если вы вообще должны использовать глобальные переменные). Строгий режим предотвращает случайное создание глобальных переменных из-за использования необъявленных переменных (например, из-за опечатки).   -  person Robin Zigmond    schedule 20.12.2018
comment
Ни один JS-движок не имеет понятия с аналогичным названием. Имена переменных либо одинаковые, либо разные.   -  person Robin Zigmond    schedule 20.12.2018
comment
Я думаю, что ваше замешательство связано с слишком буквальной интерпретацией этого комментария в вашем цитируемом фрагменте. Ошибка возникает не из-за предполагаемого сходства имени с другой переменной, а просто из-за того, что вы используете необъявленную переменную. Неважно, какие другие имена переменных вы используете.   -  person Robin Zigmond    schedule 20.12.2018
comment
@RobinZigmond Для меня это имеет смысл! Но опять же - из моей цитаты: Предположим, что глобальная переменная mistypedVariable существует(!!), присваивание mistypeVariable=17 не выполняется. Только если предположить, что mistypedVariabled существует?!?!   -  person    schedule 20.12.2018
comment
Комментарий в цитируемом коде вводит в заблуждение: часть предположения не имеет значения. На самом деле это должно выглядеть так: Предположим, что никакая переменная с точно этим именем была определена с помощью let или var,... Но обратите внимание, в чем заключалась цель фрагмента кода и комментарий: чтобы показать, что в строгом режиме намного легче выявлять орфографические ошибки.   -  person trincot    schedule 20.12.2018
comment
@AndrewL извините за откат, но код является частью цитаты, поэтому я считаю, что его следует пометить как таковой?   -  person    schedule 20.12.2018
comment
Возможный дубликат Что использует strict do в JavaScript и в чем причина этого?   -  person Patrick Roberts    schedule 20.12.2018
comment
@trincot @ RobinZigmond Спасибо за ваши последние комментарии! Сделайте это ответом, и я приму его :)   -  person    schedule 20.12.2018
comment
@RobinZigmond См. выше.   -  person    schedule 20.12.2018
comment
@gazkam готово :) (Хотя я вижу, что тринкот добрался туда первым :))   -  person Robin Zigmond    schedule 20.12.2018


Ответы (3)


Комментарий в приведенном коде вводит в заблуждение: часть «Предположение» не имеет значения. На самом деле это должно выглядеть так: "Если предположить, что никакая глобальная переменная с точно именем была определена с помощью let или var,..."

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

person trincot    schedule 20.12.2018

Как и просили, я сделаю это ответом :)

Я думаю, вы уже понимаете, что здесь происходит, и просто запутались, прочитав эту цитату о «принятии глобальной переменной ...» слишком буквально. (Я признаю, что это сформулировано таким образом, чтобы, возможно, привести к этой путанице.) Реальная ситуация очень проста и не имеет ничего общего с переменными, имеющими «похожие имена» (о которых JS не имеет понятия):

Речь идет о том, что произойдет, если вы присвоите значение переменной, которая не была официально объявлена ​​(переменные объявляются с одним из ключевых слов var, let или const). Не объявлять свои переменные — плохая практика, а в строгом режиме будет выдаваться ошибка — это хорошо и предупреждает вас о вашей ошибке. Но в нестрогом режиме JS с радостью примет это и решит, что вы хотели объявить глобальную переменную с таким именем. Это почти никогда не то, что вам на самом деле нужно, так как это загрязняет глобальное пространство имен, не информирует вас о вашей ошибке и может позже привести к всевозможным хитрым ошибкам.

person Robin Zigmond    schedule 20.12.2018
comment
Проголосуйте, но не можете разделить зеленую галочку на две части, извините :) - person ; 20.12.2018

строгий режим просто запрещает объявлять глобальные переменные за пределами глобальной области видимости?

строгий режим определенно не запрещает объявлять глобальные переменные где бы то ни было. В нестрогом режиме, если вы пишете:

someVar = 't';

он будет оцениваться как:

window.someVar = 't';

( почему это происходит? ), несмотря на запись внутри или вне области действия функции. на самом деле, строка одновременно объявляла и вычисляла переменную (посмотрите еще раз, в ней нет var, поэтому она не должна ничего объявлять!).

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

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

var someGlobalVar;
var someOtherGlobalVar;

function hello() {

    // this will make *someGlobalVar* to be redefined in the inner scope
    // someGlobalVar != window.someGlobalVar
    var someGlobalVar;

    // manipulating inner variable, not global one
    someGlobalVar = 's';


    // it's fine, you've accessed global object correctly
    window.someGlobalVar = 's';


    // you're still editing global object, because
    // there's no other variable inside of this scope having the same name
    someOtherGlobalVar = 's';

}
person mrReiha    schedule 20.12.2018