Есть ли разница между объявлением переменной:
var a=0; //1
...сюда:
a=0; //2
...или:
window.a=0; //3
в глобальном масштабе?
javascript
Дэн
источник
источник
Ответы:
Да, есть пара отличий, хотя на практике они обычно невелики.
Есть четвертый путь, а с ES2015 (ES6) есть еще два. В конце я добавил четвертый способ, но вставил пути ES2015 после # 1 (вы поймете почему), поэтому мы имеем:
Эти заявления объяснили
# 1
var a = 0;
Это создает глобальную переменную, которая также является свойством глобального объекта , к которому мы получаем доступ как
window
в браузерах (или черезthis
глобальную область видимости в нестрогом коде). В отличие от некоторых других свойств, свойство не может быть удалено с помощьюdelete
.В терминах спецификации он создает привязку идентификатора для объекта Environment Record для глобальной среды . Это делает его свойством глобального объекта, поскольку в глобальном объекте хранятся привязки идентификаторов для объекта среды. Запись среды. Вот почему свойство не удаляется: это не просто свойство, это привязка идентификатора.
Привязка (переменная) определяется до запуска первой строки кода (см. «Когда это
var
происходит» ниже).Обратите внимание, что в IE8 и более ранних версиях свойство on
window
не перечисляется (не отображается вfor..in
выражениях). В IE9, Chrome, Firefox и Opera его можно перечислить.# 1,1
let a = 0;
Это создает глобальную переменную, которая не является свойством глобального объекта. Это новая вещь с ES2015.
В терминах спецификации он создает привязку идентификатора в декларативной записи среды для глобальной среды, а не для объекта записи среды. Глобальная среда уникальна в том , раскол по окружающей среде записи, один для всех старых вещей , которая идет на глобальный объект ( объект Environment Record) и другой для всех новых вещей (
let
,const
и функции , созданныеclass
) , которые не делают перейти на глобальный объект.Привязка создается до того, как будет выполнен любой пошаговый код в его включающем блоке (в данном случае, до запуска любого глобального кода), но он никоим образом не будет доступен , пока пошаговое выполнение не достигнет
let
оператора. Как только выполнение достигаетlet
оператора, переменная становится доступной. (См. «Когдаlet
иconst
произойдет» ниже.)# 1,2
const a = 0;
Создает глобальную константу, которая не является свойством глобального объекта.
const
точно так же,let
за исключением того, что вы должны предоставить инициализатор (= value
деталь), и вы не можете изменить значение константы после ее создания. Под крышками это точно так же,let
но с привязкой к идентификатору с флагом, указывающим, что его значение нельзя изменить. Использованиеconst
делает три вещи для вас:# 2
a = 0;
Это неявно создает свойство для глобального объекта . Поскольку это нормальное свойство, вы можете удалить его. Я бы порекомендовал не делать этого, это может быть непонятно любому, кто читает ваш код позже. Если вы используете строгий режим ES5, выполнение этого (присвоение несуществующей переменной) является ошибкой. Это одна из нескольких причин использовать строгий режим.
И что интересно, опять же в IE8 и более ранних версиях свойство создано не перечисляемым (не отображается в
for..in
выражениях). Это странно, особенно учитывая № 3 ниже.# 3
window.a = 0;
Это явно создает свойство для глобального объекта, используя глобальный объект,
window
который ссылается на глобальный объект (в браузерах; некоторые среды без браузера имеют эквивалентную глобальную переменную, например, вglobal
NodeJS). Поскольку это нормальное свойство, вы можете удалить его.Это свойство является перечислимо, на IE8 и более ранние версии, а также на любом другом браузере я пробовал.
# 4
this.a = 0;
Точно так же, как # 3, за исключением того, что мы ссылаемся на глобальный объект через
this
вместо глобальногоwindow
. Это не будет работать в строгом режиме, потому что в строгом режиме глобальный кодthis
не имеет ссылки на глобальный объект (undefined
вместо него есть значение ).Удаление свойств
Что я имею в виду под «удалением» или «удалением»
a
? Именно это: Удаление свойства (полностью) с помощьюdelete
ключевого слова:delete
полностью удаляет свойство из объекта. Вы не можете сделать это с помощью свойств, добавленныхwindow
косвенно черезvar
,delete
либо либо игнорируется, либо выдает исключение (в зависимости от реализации JavaScript и того, находитесь ли вы в строгом режиме).Предупреждение : IE8 снова (и, по-видимому, ранее, и IE9-IE11 в сломанном режиме «совместимости»): он не позволит вам удалить свойства
window
объекта, даже если вам это разрешено. Хуже того, он выдает исключение при попытке ( попробуйте этот эксперимент в IE8 и в других браузерах). Поэтому при удалении сwindow
объекта вы должны быть оборонительными:Он пытается удалить свойство, и если выбрасывается исключение, он делает следующее лучшее и устанавливает для свойства значение
undefined
.Это относится только к
window
объекту и только (насколько я знаю) к IE8 и более ранним версиям (или IE9-IE11 в сломанном режиме «совместимости»). Другие браузеры могут удалятьwindow
свойства в соответствии с приведенными выше правилами.Когда
var
происходитПеременные , определенные с помощью
var
заявления создаются до любой шаг за шагом код в контексте выполнения выполняется, и поэтому свойство существует хорошо перед тем вvar
заявлении.Это может сбивать с толку, поэтому давайте посмотрим:
Живой пример:
Показать фрагмент кода
Как видите, символ
foo
определяется перед первой строкой, а символbar
- нет. Где этоvar foo = "f";
утверждение, на самом деле есть две вещи: определение символа, которое происходит до запуска первой строки кода; и выполнение присвоения этому символу, что происходит, когда строка находится в пошаговом потоке. Это называется «var
подъемом», посколькуvar foo
деталь перемещается («поднимается») в верхнюю часть области, ноfoo = "f"
деталь остается в своем первоначальном положении. (См. Плохо неправильно понятvar
в моем анемичном небольшом блоге.)Когда
let
иconst
произойдетlet
иconst
отличаются отvar
нескольких способов. Способ, который имеет отношение к этому вопросу, заключается в том, что хотя определяемая ими привязка создается до запуска любого пошагового кода, она не доступна, пока не будет достигнут операторlet
илиconst
.Итак, пока это работает:
Это выдает ошибку:
Остальные два способа , которыми
let
иconst
отличаются отvar
, которые не являются на самом деле отношение к вопросу, являются:var
всегда применяется ко всему контексту выполнения (по всему глобальному коду или по всему коду функции в функции, где он появляется), ноlet
иconst
применяется только внутри блока, в котором они появляются. То естьvar
имеет функцию (или глобальную) область видимости, ноlet
иconst
имеет область видимости блока.Повторение
var a
в том же контексте безвредно, но если у вас естьlet a
(илиconst a
), наличие другогоlet a
или aconst a
или avar a
является синтаксической ошибкой.Вот пример, демонстрирующий это
let
иconst
вступающий в силу немедленно в их блоке до запуска любого кода в этом блоке, но недоступный до оператораlet
orconst
:Обратите внимание, что второй
console.log
сбой, вместо доступа кa
извне блока.Не по теме: избегать загромождения глобального объекта (
window
)window
Объект получает очень, очень завален свойствами. По возможности, настоятельно рекомендуем не добавлять в беспорядок. Вместо этого оберните ваши символы в небольшой пакет и экспортируйте не более одного символа вwindow
объект. (Я часто не экспортирую никакие символы вwindow
объект.) Вы можете использовать функцию для хранения всего вашего кода, чтобы содержать ваши символы, и эта функция может быть анонимной, если вам нравится:В этом примере мы определяем функцию и выполняем ее сразу (
()
в конце).Функция, используемая таким образом, часто называется областью видимости . Функции, определенные в функции определения объема, могут получать доступ к переменным, определенным в функции определения объема, потому что они являются замыканиями для этих данных (см. Закрытия не сложны в моем анемичном небольшом блоге).
источник
window['a']=0
сделать, чтобы было ясно, что я использую окно как карту? этоwindow
особый таким образом, что некоторые браузеры не позволяют это и заставить меня использоватьwindow.a
?window.a = 0;
работает только в браузерных средах и только по соглашению. Связывание глобального объекта в переменную с именемwindow
не в ES Spec и поэтому не будет работать, например, V8 или Node.js, в то время какthis.a = 0;
(при вызове в глобальном контексте выполнения) , будет работать в любой среде , поскольку спецификации действительно указать что должно быть глобальный объект. Если вы переносите код в IIFE, как в разделе « Не по теме », вы можете передать его в качестве параметра с именем или получить прямую ссылку на глобальный объект.this
window
global
var a = 0;
автоматически, становится свойством глобального объекта. Если я объявлюvar b = 0;
в объявлении функции, будет ли это также свойство какого-то базового объекта?Сохраняя это простым:
Код выше дает глобальную переменную области видимости
Этот код даст переменную, которая будет использоваться в текущей области видимости и под ней
Обычно это то же самое, что глобальная переменная.
источник
a
под текущая сфера Ты можешь. Кроме того, ваше использование «глобальной переменной» немного не подходит - два места, где вы говорите «глобальная переменная», не более глобально, чем место, где вы этого не говорите.Есть ли глобальный объект, от которого все переменные зависают по умолчанию? Например: 'объявление globals.noVar'
источник
window.*
декларации. Это объявление выглядит наиболее безопасным от копирования вашего кода, а также ясно.Основано на превосходном ответе TJ Crowder : ( Не по теме: избегать беспорядка
window
)Это пример его идеи:
Html
init.js (на основании этого ответа )
script.js
Вот плнкр . Надеюсь, это поможет!
источник
В глобальном масштабе нет семантической разницы.
Но вы действительно должны избегать
a=0
поскольку вы устанавливаете значение в необъявленную переменную.Также используйте замыкания, чтобы вообще не редактировать глобальную область видимости.
Всегда используйте затворы и всегда поднимайте их в глобальную область, когда это абсолютно необходимо. В любом случае вы должны использовать асинхронную обработку событий для большей части вашего общения.
Как упомянул @AvianMoncellor, есть ошибка IE с
var a = foo
объявляется только глобальная область видимости файла. Это проблема пресловутого сломанного интерпретатора IE. Эта ошибка звучит знакомо, так что, вероятно, это правда.Так что придерживайтесь
window.globalName = someLocalpointer
источник
delete
var
var
. Это просто совершенно разные механизмы, которые имеют практически одинаковый практический результат. :-)var
прыгает до упора.