Лекция
Привет, сегодня поговорим про глобальный объект, обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое глобальный объект , настоятельно рекомендую прочитать все из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend).
Механизм работы функций и переменных в JavaScript очень отличается от большинства языков.
Чтобы его понять, мы в этой главе рассмотрим переменные и функции в глобальной области. А в следующей — пойдем дальше.
Глобальными называют переменные и функции, которые не находятся внутри какой-то функции. То есть, иными словами, если переменная или функция не находятся внутри конструкции function
, то они — «глобальные».
В JavaScript все глобальные переменные и функции являются свойствами специального объекта, который называется «глобальный объект» (global object
).
В браузере этот объект явно доступен под именем window
. Объект window
одновременно является глобальным объектом и содержит ряд свойств и методов для работы с окном браузера, но нас здесь интересует только его роль как глобального объекта.
В других окружениях, например Node.JS, глобальный объект может быть недоступен в явном виде, но суть происходящего от этого не изменяется, поэтому далее для обозначения глобального объекта мы будем использовать "window"
.
Присваивая или читая глобальную переменную, мы, фактически, работаем со свойствамиwindow
.
Например:
1 |
var a = 5; // объявление var создает свойство window.a |
2 |
alert(window.a); // 5 |
Создать переменную можно и явным присваиванием в window
:
1 |
window.a = 5; |
2 |
alert(a); // 5 |
Выполнение скрипта происходит в две фазы:
Во время инициализации скрипт сканируется на предмет объявления функций вида Function Declaration, а затем — на предмет объявления переменных var
. Каждое такое объявление добавляется в window
.
Функции, объявленные как Function Declaration, создаются сразу работающими, а переменные — равными undefined
.
Присваивание (=
) значений переменных происходит на второй фазе, когда поток выполнения доходит до соответствующей строчки кода.
В начале кода ниже указано содержание глобального объекта на момент окончания инициализации:
1 |
// По окончании инициализации, до выполнения кода: |
2 |
// window = { f: function, a: undefined, g: undefined } |
3 |
4 |
var a = 5; // при инициализации дает: window.a=undefined |
5 |
6 |
function f(arg) { /*...*/ } // при инициализации дает: window.f = function |
7 |
8 |
var g = function (arg) { /*...*/ }; // при инициализации дает: window.g = undefined |
Кстати, тот факт, что к началу выполнения кода переменные и функции уже содержатся в window
, можно легко проверить:
1 |
alert( "a" in window); // true, т.к. есть свойство window.a |
2 |
alert(a); // равно undefined, присваивание будет выполнено далее |
3 |
alert(f); // function ..., готовая к выполнению функция |
4 |
alert(g); // undefined, т.к. это переменная, а не Function Declaration |
5 |
6 |
var a = 5; |
7 |
function f() { /*...*/ } |
8 |
var g = function () { /*...*/ }; |
В старом стандарте JavaScript переменную можно было создать и без объявленияvar
:
1 |
a = 5; |
2 |
3 |
alert(a); // 5 |
Такое присвоение, как и var a = 5
, создает свойство window.a = 5
. Отличие отvar a = 5
— в том, что переменная будет создана не на этапе входа в область видимости, а в момент присвоения.
Сравните два кода ниже.
Первый выведет undefined
, так как переменная была добавлена в window
на фазе инициализации:
1 |
alert(a); // undefined |
2 |
3 |
var a = 5; |
Второй код выведет ошибку, так как переменной еще не существует:
1 |
alert(a); // error, a is not defined |
2 |
3 |
a = 5; |
Вообще, рекомендуется всегда объявлять переменные через var
.
В современном стандарте присваивание без var
вызовет ошибку:
1 |
'use strict' ; |
2 |
a = 5; // error, a is not defined |
for, if...
не влияют на видимость переменныхФигурные скобки, которые используются в for, while, if
, в отличие от объявлений функции, имеют «декоративный» характер.
В JavaScript нет разницы между объявлением вне блока:
1 |
var
i; |
2 |
{ |
3 |
i = 5; |
4 |
} |
1 |
i = 5; |
2 |
{ |
3 |
var
i; |
4 |
} |
Также нет разницы между объявлением в цикле и вне его:
1 |
for ( var
i=0; i<5; i++) { } |
1 |
var i; |
2 |
for (i=0; i<5; i++) { } |
В обоих случаях переменная будет создана до выполнения цикла, на стадии инициализации, и ее значение будет сохранено после окончания цикла.
Объявлений var
может быть сколько угодно:
1 |
var i = 10; |
2 |
3 |
for ( var i=0; i<20; i++) { |
4 |
... |
5 |
} |
6 |
7 |
var i = 5; |
Все var
будут обработаны один раз, на фазе инициализации.
На фазе исполнения объявления var
будут проигнорированы: они уже были обработаны. Об этом говорит сайт https://intellect.icu . Зато будут выполнены присваивания.
window
в IE8-В старых IE есть две забавные ошибки при работе с переменными в window
:
id
элемента, приведет к ошибке:
1 |
< div id = "a" >...</ div > |
2 |
<script> |
3 |
a = 5; // ошибка в IE<9! Правильно будет "var a = 5" |
4 |
alert(a); // никогда не сработает |
5 |
</script> |
А если сделать через var
, то все будет хорошо.
Это была реклама того, что надо везде ставить var
.
window
. Следующий код «умрет» в IE<9:
1 |
<script> |
2 |
// рекурсия через функцию, явно записанную в window |
3 |
window.recurse = function (times) { |
4 |
if (times !== 0) recurse(times-1); |
5 |
} |
6 |
7 |
recurse(13); |
8 |
</script> |
Проблема здесь возникает из-за того, что функция напрямую присвоена вwindow.recurse = ...
. Ее не будет при обычном объявлении функции.
Этот пример выдаст ошибку только в настоящем IE8! Не IE9 в режиме эмуляции. Вообще, режим эмуляции позволяет отлавливать где-то 95% несовместимостей и проблем, а для оставшихся 5% вам нужен будет настоящий IE8 в виртуальной машине.
В результате инициализации, к началу выполнения кода:
Function Declaration
, создаются полностью и готовы к использованию.undefined
. Присваивания выполнятся позже, когда выполнение дойдет до них.
К сожалению, в одной статье не просто дать все знания про глобальный объект. Но я - старался. Если ты проявишь интерес к раскрытию подробностей,я обязательно напишу продолжение! Надеюсь, что теперь ты понял что такое глобальный объект и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Комментарии
Оставить комментарий
Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Термины: Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)