Var js что это
Перейти к содержимому

Var js что это

  • автор:

Устаревшее ключевое слово «var»

Информация, приведенная в этой статье, полезна для понимания старых скриптов.

Мы не пишем современный код таким образом.

В самой первой главе про переменные мы ознакомились с тремя способами объявления переменных:

let и const ведут себя одинаково по отношению к лексическому окружению, области видимости.

Но var – это совершенно другой зверь, берущий своё начало с давних времён. Обычно var не используется в современных скриптах, но всё ещё может скрываться в старых.

Если в данный момент вы не работаете с подобными скриптами, вы можете пропустить или отложить прочтение данной главы, однако, есть шанс, что вы столкнётесь с var в будущем.

На первый взгляд, поведение var похоже на let . Например, объявление переменной:

function sayHi() < var phrase = "Привет"; // локальная переменная, "var" вместо "let" alert(phrase); // Привет >sayHi(); alert(phrase); // Ошибка: phrase не определена

…Однако, отличия всё же есть.

Для «var» не существует блочной области видимости

Область видимости переменных var ограничивается либо функцией, либо, если переменная глобальная, то скриптом. Такие переменные доступны за пределами блока.

if (true) < var test = true; // используем var вместо let >alert(test); // true, переменная существует вне блока if

Так как var игнорирует блоки, мы получили глобальную переменную test .

А если бы мы использовали let test вместо var test , тогда переменная была бы видна только внутри if :

if (true) < let test = true; // используем let >alert(test); // Error: test is not defined

Аналогично для циклов: var не может быть блочной или локальной внутри цикла:

for (var i = 0; i < 10; i++) < // . >alert(i); // 10, переменная i доступна вне цикла, т.к. является глобальной переменной

Если блок кода находится внутри функции, то var становится локальной переменной в этой функции:

function sayHi() < if (true) < var phrase = "Привет"; >alert(phrase); // срабатывает и выводит "Привет" > sayHi(); alert(phrase); // Ошибка: phrase не определена (видна в консоли разработчика)

Как мы видим, var выходит за пределы блоков if , for и подобных. Это происходит потому, что на заре развития JavaScript блоки кода не имели лексического окружения. Поэтому можно сказать, что var – это пережиток прошлого.

«var» допускает повторное объявление

Если в блоке кода дважды объявить одну и ту же переменную let , будет ошибка:

let user; let user; // SyntaxError: 'user' has already been declared

Используя var , можно переобъявлять переменную сколько угодно раз. Повторные var игнорируются:

var user = "Pete"; var user; // ничего не делает, переменная объявлена раньше // . нет ошибки alert(user); // Pete

Если дополнительно присвоить значение, то переменная примет новое значение:

var user = "Pete"; var user = "John"; alert(user); // John

«var» обрабатываются в начале запуска функции

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

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

function sayHi() < phrase = "Привет"; alert(phrase); var phrase; >sayHi();

…Технически полностью эквивалентен следующему (объявление переменной var phrase перемещено в начало функции):

function sayHi() < var phrase; phrase = "Привет"; alert(phrase); >sayHi();

…И даже коду ниже (как вы помните, блочная область видимости игнорируется):

function sayHi() < phrase = "Привет"; // (*) if (false) < var phrase; >alert(phrase); > sayHi();

Это поведение называется «hoisting» (всплытие, поднятие), потому что все объявления переменных var «всплывают» в самый верх функции.

В примере выше if (false) условие никогда не выполнится. Но это никаким образом не препятствует созданию переменной var phrase , которая находится внутри него, поскольку объявления var «всплывают» в начало функции. Т.е. в момент присвоения значения (*) переменная уже существует.

Объявления переменных «всплывают», но присваивания значений – нет.

Это проще всего продемонстрировать на примере:

function sayHi() < alert(phrase); var phrase = "Привет"; >sayHi();

Строка var phrase = «Привет» состоит из двух действий:

  1. Объявление переменной var
  2. Присвоение значения в переменную = .

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

function sayHi() < var phrase; // объявление переменной срабатывает вначале. alert(phrase); // undefined phrase = "Привет"; // . присвоение - в момент, когда исполнится данная строка кода. >sayHi();

Поскольку все объявления переменных var обрабатываются в начале функции, мы можем ссылаться на них в любом месте. Однако, переменные имеют значение undefined до строки с присвоением значения.

В обоих примерах выше вызов alert происходил без ошибки, потому что переменная phrase уже существовала. Но её значение ещё не было присвоено, поэтому мы получали undefined .

IIFE

В прошлом, поскольку существовал только var , а он не имел блочной области видимости, программисты придумали способ её эмулировать. Этот способ получил название «Immediately-invoked function expressions» (сокращенно IIFE).

Это не то, что мы должны использовать сегодня, но, так как вы можете встретить это в старых скриптах, полезно понимать принцип работы.

IIFE выглядит следующим образом:

(function() < var message = "Hello"; alert(message); // Hello >)();

Здесь создаётся и немедленно вызывается Function Expression. Так что код выполняется сразу же и у него есть свои локальные переменные.

Function Expression обёрнуто в скобки (function <. >) , потому что, когда JavaScript встречает «function» в основном потоке кода, он воспринимает это как начало Function Declaration. Но у Function Declaration должно быть имя, так что такой код вызовет ошибку:

// Пробуем объявить и сразу же вызвать функцию function() < // ();

Даже если мы скажем: «хорошо, давайте добавим имя», – это не сработает, потому что JavaScript не позволяет вызывать Function Declaration немедленно.

// ошибка синтаксиса из-за скобок ниже function go() < >(); // 

Так что скобки вокруг функции – это трюк, который позволяет объяснить JavaScript, что функция была создана в контексте другого выражения, а значит, что это Function Expression: ей не нужно имя и её можно вызвать немедленно.

Помимо круглых скобок существуют и другие способы сообщить JavaScript, что мы имеем в виду Function Expression:

// Способы создания IIFE (function() < alert("Круглые скобки вокруг функции"); >)(); (function() < alert("Круглые скобки вокруг всего выражения"); >()); !function() < alert("Выражение начинается с логического оператора НЕ"); >(); +function() < alert("Выражение начинается с унарного плюса"); >();

Во всех перечисленных случаях мы объявляем Function Expression и немедленно запускаем его. Ещё раз отметим: в настоящее время необходимости писать подобный код нет.

Итого

Существует 2 основных отличия var от let/const :

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

Есть ещё одно небольшое отличие, относящееся к глобальному объекту, мы рассмотрим его в следующей главе.

Эти особенности, как правило, не очень хорошо влияют на код. Блочная область видимости – это удобно. Поэтому много лет назад let и const были введены в стандарт и сейчас являются основным способом объявления переменных.

Var js что это

Оператор var объявляет переменную, инициализируя её, при необходимости.

Интерактивный пример

Синтаксис

var varname1 [= value1 [, varname2 [, varname3 . [, varnameN]]]];

Имя переменной. Может использоваться любой допустимый идентификатор.

Значение переменной. Любое допустимое выражение. По умолчанию значение undefined.

Описание

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

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

1. Объявленные переменные ограничены контекстом выполнения, в котором они были объявлены. Необъявленные переменные всегда глобальны.

function x()  y = 1; // возбудит ReferenceError в "строгом режиме" var z = 2; > x(); console.log(y); // выведет "1" console.log(z); // возбудит ReferenceError: z не определён вне x 

2. Объявленные переменные инициализируются до выполнения любого кода. Необъявленные переменные не существуют до тех пор, пока к ним не выполнено присваивание.

.log(a); // Возбудит ReferenceError. console.log("still going. "); // Не выполнится. 
var a; console.log(a); // Выведет "undefined" или "", в зависимости от браузера. console.log("still going. "); // Выведет "still going. ". 

3. Объявленные переменные, независимо от контекста выполнения, являются ненастраиваемыми свойствами. Необъявленные переменные это настраиваемые свойства (т.е. их можно удалять).

var a = 1; b = 2; delete this.a; // Возбудит TypeError в "строгом режиме". В "нестрогом режиме" будет ошибка без уведомления. delete this.b; console.log(a, b); // Возбудит ReferenceError. // Свойство 'b' было удалено и больше не существует. 

Из-за перечисленных различий, использование необъявленных переменных может привести к непредсказуемым последствиям. Рекомендовано всегда объявлять переменные, вне зависимости, находятся они внутри функции или в глобальном контексте. Присваивание значения необъявленной переменной в строгом режиме (en-US) ECMAScript 5 возбуждает ошибку.

Поднятие переменных

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

= 2; var bla; // . // читается как: var bla; bla = 2; 

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

Важно отметить, что подъем будет влиять на объявление переменной, но не на инициализацию её значения. Значение присваивается при выполнении оператора присваивания:

function do_something()  console.log(bar); // выведет undefined var bar = 111; console.log(bar); // выведет 111 > // . неявно понимается как: function do_something()  var bar; console.log(bar); // выведет undefined bar = 111; console.log(bar); // выведет 111 > 

Что такое var в JavaScript?

Типы переменных в языке JavaScript не объявляются очевидно, тем не менее они присутствуют. Интерпретатор понимает что записывается в переменную и на основании этого добавляет тип к этой переменной.

В ходе программы мы можем перезаписывать значение переменной, при этом мы можем указывать новый тип переменной.

К примеру, изначально был записан тип float (число с точкой), но потом можно записать другой тип данных:

var first_num = 23.2 // Тип данных float var first_num = "1" // Тип данных string

Ниже приводим несколько существующих типов данных в языке JavaScript:

  • var some = 1 Integer - целые числа;
  • var some = 1.12 Float - числа с плавающей точкой;
  • var some = "Привет" String - строки;
  • var some = true Boolean - принимают только true или же false.

Var, let и const в JavaScript

Пока я разбирался что к чему в основах JavaScript, я наткнулся на три способа объявления переменных, а именно var, let и const. В данной статье я попытаюсь обобщить различия этих операторов присваивания.

Чтобы по-настоящему понять разницу между var, let и const, нам необходимо разобраться в следующих понятиях:

  • Объявление переменной;
  • Инициализация переменной;
  • Область видимости;
  • Механизм hoisting («поднятие»).

Объявление переменной

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

var foo; // объявление переменной
console.log(foo); // logs →undefined

Инициализация переменной

Инициализация переменной — это процесс присваивания значения переменной. Поэтому, когда мы определяем связь между ключевым словом var, интерпретатор присваивает значение undefined.

var foo; // объявление переменной
console.log(foo); // logs →undefined
foo = “something”; // Initialization
console.log(foo); // logs →something

Область видимости

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

Существует 2 типа области видимости:

  • Функциональная область видимости;
  • Блочная область видимости.

Функциональная область видимости

Переменные, объявленные внутри функции, входят в область видимости этой функции, а также в область видимости вложенных в нее функций, независимо от блоков.

function foo() if(true) var v = “var inside the if block”; 
console.log(v); //logs →var inside the if block
>
v = “var outside the if block”;
console.log(v); //logs →var outside the if block
>
foo();

Блочная область видимости

Переменные, объявленные внутри блока, входят в область видимости только этого блока, а также вложенных в него блоков, но не за пределами блока, даже если это все одна функция. В блоки входят if. else и циклы.

function bar() if(true) let l = “let inside the if block”; 
console.log(l); //logs →let inside the if block
>
console.log(l); // Uncaught Reference Error: l is not defined
>
bar();

Поднятие

В веб-документации MDN говорится:

«Поднятие — это термин, использование которого вы не найдете ни в одной нормативной документации JavaScript до спецификации языка ES2015. Предполагалось, что поднятие — это обобщенный способ видения того, как работает контекст исполнения (особенно создание и исполнение стадий) в JavaScript. Однако это понятие по началу может сбивать с толку.

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

console.log(foo); //logs →undefined 
// это не приводит к ошибке, однако значение →undefined;
//это происходит из-за поднятия
var foo = “something”; //Инициализация
console.log(foo); //logs →something

Как можно упростить оценку интерпретатора JS для кода выше:

var foo; // Поднятое объявление ‘foo’
console.log(foo); записывает значение →undefined;
foo = “something”;
console.log(foo); //записывает значение →something

Оператор var объявляет переменную, опционально присваивая ей значение. Любая переменная, объявленная оператором var, имеет функциональную область видимости и идентифицирует объявленные переменные с помощью ключевого слова var. Такие переменные поднятые, а их первоначальное значение — undefined.

console.log(foo); //logs →undefined
var foo;
//код выше не приводит к ошибке из-за поднятия;

Оператор let объявляет локальную переменную. Любая переменная, объявленная с помощью let, имеет блочную область видимости. Значения подняты и не инициализированы.

let foo;
console.log(foo); // Uncaught Reference Error: l is not defined
// код выше приводит к ошибке, потому что значение переменной не инициализировано;

Связи let создаются сверху области видимости конкретного блока, содержащего определение, часто называемого поднятием. В отличие от переменных, объявленных с помощью var, которые начинаются со значения undefined, переменные let не инициализируются, пока им не присвоится значение. Обращение к переменной до инициализации вызовет Reference Error (ошибка использования несуществующего названия).

const

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

Следовательно, const должен быть всегда инициализирован при объявлении, иначе возникает ошибка.

const foo = “something”;
foo = “other thing”; // Uncaught TypeError: Assignment to constant variable.
const bar; //Uncaught SyntaxError: Missing initializer in const declaration

Стоит отметить, что когда const связан с объектом, сам объект нельзя изменить, и const будет указывать на тот же самый объект. Однако изменения внутри объекта допустимы.

const score = ;
score.visitors = 1; // Можно
score = ; // Uncaught TypeError: Assignment to constant variable.
// Нельзя

Один последний факт:

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

function funFact() isGloballyAvailable = true;
>
funFact();
console.log(isGloballyAvailable); // записывает true

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

В нашем случае интерпретатор не найдет ‘isGloballyAvailable’ даже в глобальной области видимости, поэтому он автоматически туда ее добавит.

Это невероятно опасный процесс, которого лучше не допускать. Поэтому имейте в виду, что объявлять переменные без ключевых слов var, let и const нельзя.

Так, когда использовать var, let или const?

ES2015(ES6) представил let и const. Зачем JavaScript разработчикам их вводить? Может, чтобы исправить проблемы, возникающие с var, или для улучшения читабельность кода?

Одна главная проблема с var связана с тем, что он позволяет переназначать переменные в коде, из-за чего не выбрасываются ошибки. Это приводит к различным побочным эффектам в коде.

Распространенное мнение, которое сходится с моим:

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

А let используйте, если значение в будущем изменится.

Где бы был полезен var, я не представляю.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *