Какова цель ключевого слова var и когда я должен его использовать (или опустить)?

1330

ПРИМЕЧАНИЕ. Этот вопрос задавался с точки зрения ECMAScript версии 3 или 5. Ответы могут устареть с введением новых функций в выпуске ECMAScript 6.

Что такое функция ключевого слова var в JavaScript и какая разница между

var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;

и

someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;

?

Когда вы используете один из них и почему/что он делает?

  • 32
    Всегда используйте var! Даже в глобальном масштабе, в противном случае у вас могут возникнуть проблемы с IE (по крайней мере, версия 6). Я говорю это на собственном опыте.
  • 2
    При цепочке объявлений var влияет ли поведение на новую строку после запятой? var x = 1, y = 2, [return] z = 3;
Показать ещё 7 комментариев
Теги:
ecmascript-5
keyword

18 ответов

1324
Лучший ответ

Если вы находитесь в глобальной области, то нет большой разницы. Прочтите ответ Kangax для объяснения

Если вы находитесь в функции, тогда var создаст локальную переменную, "no var" будет искать цепочку областей действия до тех пор, пока не найдет переменную или не попадет в глобальную область (в какой момент она ее создаст):

// These are both globals
var foo = 1;
bar = 2;

function()
{
    var foo = 1; // Local
    bar = 2;     // Global

    // Execute an anonymous function
    (function()
    {
        var wibble = 1; // Local
        foo = 2; // Inherits from scope above (creating a closure)
        moo = 3; // Global
    }())
}

Если вы не выполняете задание, вам нужно использовать var:

var x; // Declare x
  • 25
    «Не очень ли большая разница» == «Нет разницы»?
  • 63
    Ну, на самом деле да, есть разница :) Важна ли эта разница - другой вопрос. Смотрите мой ответ ниже: stackoverflow.com/questions/1470488/…
Показать ещё 14 комментариев
699

Есть разница.

var x = 1 объявляет переменную x в текущей области (также как контекст исполнения). Если объявление появляется в функции - объявляется локальная переменная; если он в глобальной области действия - объявлена ​​глобальная переменная.

x = 1, с другой стороны, является просто присвоением свойства. Сначала он пытается разрешить x по цепочке цепей. Если он находит его где-либо в этой цепочке видимости, он выполняет назначение; если он не находит x, только тогда он создает свойство x для глобального объекта (который является объектом верхнего уровня в цепочке областей видимости).

Теперь обратите внимание, что он не объявляет глобальную переменную, он создает глобальное свойство.

Разница между двумя является тонкой и может быть запутанной, если вы не понимаете, что объявления переменных также создают свойства (только для объекта Variable) и что каждое свойство в Javascript (хорошо, ECMAScript) имеет определенные флаги, которые описывают их свойства - ReadOnly, DontEnum и DontDelete.

Поскольку объявление переменной создает свойство с флагом DontDelete, разница между var x = 1 и x = 1 (при выполнении в глобальной области) заключается в том, что первое объявление одной переменной - создает свойство DontDelete'able, а последнее - "т. Как следствие, свойство, созданное с помощью этого неявного присваивания, затем может быть удалено из глобального объекта, а прежний - тот, который создан через объявление переменной - не может быть удален.

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

Надеюсь, что все это имеет смысл:)


[Обновить 2010/12/16]

В ES5 (ECMAScript 5, недавно стандартизованный 5-й выпуск языка) существует так называемый "строгий режим" - режим выбора языка, который слегка изменяет поведение незадекларированных назначений. В строгом режиме присвоение необъявленного идентификатора является ReferenceError. Обоснованием для этого было уловить случайные назначения, предотвращая создание нежелательных глобальных свойств. Некоторые из новых браузеров уже начали откатывать поддержку строгого режима. См., Например, мою таблицу сопоставлений.

  • 0
    Если я правильно помню, я думаю, что однажды нашел способ, чтобы иметь возможность delete переменную, объявленную var, с помощью некоторого взлома eval . Если я помню точную уловку, я отправлю здесь.
  • 3
    @Mageek Возможно, он рассматривает объявленные eval переменные, которые можно удалить. Я написал пост в блоге об этом однажды.
Показать ещё 10 комментариев
124

Говорить, что разница между локальными и глобальными "не совсем точна.

Лучше подумать об этом как о различии между локальным и ближайшим. Ближайший, безусловно, может быть глобальным, но это не всегда так.

/* global scope */
var local = true;
var global = true;

function outer() {
    /* local scope */
    var local = true;
    var global = false;

    /* nearest scope = outer */
    local = !global;

    function inner() {
        /* nearest scope = outer */
        local = false;
        global = false;

        /* nearest scope = undefined */
        /* defaults to defining a global */
        public = global;
    }
}
  • 3
    Разве ближайшая область видимости не является outer где вы определяете var global = false; ?
  • 0
    @Snekse: «Ближайший» не применяется, когда <code> var global = false; </ code> объявлен. В этом объявлении «global» помещается в область видимости external (), потому что в объявлении используется «var». Поскольку 'var' не используется в inner (), он изменит значение на следующем уровне вверх, который является external ().
Показать ещё 1 комментарий
73

Когда Javascript выполняется в браузере, весь ваш код окружен оператором with, например:

with (window) {
    //Your code
}

Дополнительная информация о with - MDN

Так как var объявляет переменную в текущей области, нет разницы между объявлением var внутри окна и не объявлением вообще.

Разница возникает, когда вы не находитесь непосредственно внутри окна, например. внутри функции или внутри блока.

Использование var позволяет скрыть внешние переменные с тем же именем. Таким образом, вы можете моделировать переменную "private", но эту другую тему.

Правило большого пальца - всегда использовать var, потому что иначе вы рискуете ввести тонкие ошибки.

EDIT: После критики, которую я получил, я хотел бы подчеркнуть следующее:

  • var объявляет переменную в текущей области
  • Глобальная область действия window
  • Не используя var неявно объявляет var в глобальной области (окне)
  • Объявление переменной в глобальной области (окне) с помощью var аналогично исключению.
  • Объявление переменной в областях, отличных от окна, с помощью var - это не одно и то же как объявление переменной без var
  • Всегда объявлять var явно, потому что это хорошая практика
  • 1
    Я не отрицал вас, но область видимости, вероятно, лучше слова, чем окно. У тебя все объяснения немного тупые.
  • 4
    Я просто называю вещи своим именем, вы хотите назвать это «глобальной областью видимости», это нормально, но на стороне клиента, по соглашению, это объект окна, который является последним элементом цепочки областей действия, поэтому вы можете вызывать каждый Функция и каждый объект в окне без записи "окна".
Показать ещё 4 комментария
38

Вы всегда должны использовать ключевое слово var для объявления переменных. Зачем? Хорошая практика кодирования должна быть достаточной причины сама по себе, но объявление переменной без ключевого слова var означает, что она объявлена ​​в области global (такая переменная, как это называется "подразумеваемая" глобальная), Douglas Crockford рекомендует никогда не использовать подразумеваемые глобальные переменные, и согласно Правилам кодирования Apple JavaScript:

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

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

  • 13
    «Хорошая практика кодирования» никогда не должна быть достаточной причиной сама по себе. Это равносильно тому, что «некоторые ребята в Интернете сказали, что так должен выглядеть мой код». Это даже менее справедливо, чем «мой учитель сказал», если только кто-то не понимает причину этого правила.
  • 0
    @cHao Я думаю, что good coding practice всегда является достаточной причиной, если это рекомендуемая лучшая практика, которой пользуются несколько авторов Javascript.
Показать ещё 1 комментарий
26

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

<script>
one();

function one()
{
    for (i = 0;i < 10;i++)
    {
        two();
        alert(i);
    }
}

function two()
{
    i = 1;
}
</script>

(i есть reset на каждой итерации цикла, так как он не объявлен локально в цикле for, но глобально), что в конечном итоге приводит к бесконечному циклу

  • 0
    Хлоп! Я могу только представить все ошибки, которые могли быть вызваны этой опечаткой.
  • 2
    мне любопытно, почему вы передаете мне в качестве аргумента два ()? (внутри цикла for) это избыточно?
Показать ещё 1 комментарий
12

Я бы сказал, что лучше использовать var в большинстве ситуаций.

Локальные переменные всегда быстрее переменных в глобальной области.

Если вы не используете var, чтобы объявить переменную, переменная будет в глобальной области.

Для получения дополнительной информации вы можете выполнить поиск "JavaScript с цепочкой цепей" в Google.

  • 0
    Если вы объявите переменную с помощью ключевого слова var, она будет создана во время выполнения, поэтому не должна ли она быть медленнее? Потому что другой создается в разобранном времени.
  • 0
    @RyuKaplan - эй, это правда? Я попробовал поискать в Google и не смог получить никакой информации по этому вопросу! У вас есть источник полномочий для этого утверждения? Спасибо
Показать ещё 1 комментарий
8

другое различие например

var a = a || [] ; // works 

while

a = a || [] ; // a is undefined error.
  • 1
    Не могли бы вы объяснить, почему это работает в случае переменной, определенной с помощью 'var', и переменной, не определенной с помощью var? Создается ли переменная до оценки правой части присваивания в случае var ?
  • 6
    @Lucek, поскольку var a поднимается до верхней части области и устанавливается в значение null, которое объявляет, но не инициализирует переменную, тогда в присваивании у вас есть ссылка на неопределенную переменную null, которая оценивается как false, и установите присваивание равным [] , В последнем у вас есть присваивание свойству a свойства a . Вы можете присвоить несуществующему свойству - создавая его по присваиванию, но вы не можете читать из несуществующего свойства без получения ReferenceError .
Показать ещё 1 комментарий
7

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

7

Без var - глобальной переменной.

Настоятельно рекомендуется ВСЕГДА использовать оператор var, поскольку глобальная переменная init в локальном контексте - зло. Но, если вам нужен этот грязный трюк, вы должны написать комментарий в начале страницы:

/* global: varname1, varname2... */
4

Не используйте var!

var был способом pre-ES6 для объявления переменной. Мы сейчас в будущем, и вы должны быть кодированием как таковым.

Используйте const и let

const следует использовать в 95% случаев. Это делает так, чтобы переменная-ссылка не могла измениться, поэтому свойства массива, объекта и DOM node могут меняться и, вероятно, должны быть const.

let следует использовать для любой переменной, ожидающей переназначения. Это включает в себя цикл for. Если вы пишете varName = после инициализации, используйте let.

Оба имеют область охвата уровня блока, как и ожидалось на большинстве других языков.

  • 2
    Замените все, что вы 'var' на 'const' (заменить все). Вы быстро заметите, где находятся ваши переназначенные переменные. Если у вас их слишком много, вы, вероятно, закодируете анти-шаблонно: большинство переназначаемых переменных могут быть встроены в замыкания или как свойства объекта. Если у вас есть несколько: используйте «пусть» для них. Наконец, если некоторые переменные вообще не делаются с помощью var, они останутся необъявленными и все еще присутствуют в глобальном пространстве, будьте осторожны. Что касается комментария @Gibolt «внутри цикла for», также рекомендуется избегать таких циклов в «95% случаев» ;-): методы массива хороши.
  • 0
    Говоря, что const следует использовать в 95% случаев, кажется, что мы уходим от хорошей практики и в догму.
2

Это пример кода, который я написал для вас, чтобы понять эту концепцию:

var foo = 5; 
bar = 2;     
fooba = 3;

// Execute an anonymous function
(function() {    
    bar = 100;             //overwrites global scope bar
    var foo = 4;           //a new foo variable is created in this' function scope
    var fooba = 900;       //same as above
    document.write(foo);   //prints 4
    document.write(bar);   //prints 100
    document.write(fooba); //prints 900
})();

document.write('<br/>');
document.write('<br/>');
document.write(foo);       //prints 5
document.write(bar);       //prints 100
document.write(fooba);     //prints 3
  • 2
    Функция ни в коем случае не является «анонимной». На самом деле, он назван настолько явно, насколько это возможно.
  • 0
    Спасибо за редактирование вашего ответа в ответ на комментарий Инго Бюрка, чтобы сделать «анонимную функцию» фактически анонимной.
1

Внутри кода вы, если используете переменную без использования var, тогда происходит то, что автоматически var var_name помещается в глобальную область, например:

someFunction() {
    var a = some_value; /*a has local scope and it cannot be accessed when this
    function is not active*/
    b = a; /*here it places "var b" at top of script i.e. gives b global scope or
    uses already defined global variable b */
}
0

@Chris S дал хороший пример, демонстрирующий практическую разницу (и опасность) между var и no var. Здесь еще один, я считаю, что это особенно опасно, потому что разница видна только в асинхронной среде, что позволяет легко проскальзывать во время тестирования.

Как вы ожидаете, следующие фрагменты кода ["text"]:

function var_fun() {
  let array = []
  array.push('text')
  return array
}

console.log(var_fun())

Так делает следующий фрагмент (обратите внимание на отсутствующий let до array):

function var_fun() {
  array = []
  array.push('text')
  return array
}

console.log(var_fun())

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

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

var_fun().then(result => {console.log(result)})

Но ведет себя по-разному с несколькими:

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})

Использование пусть однако:

function var_fun() {
  let array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})
0

Вам следует использовать ключевое слово var, если вы не намерены привязывать переменную к объекту window в браузере. Здесь ссылка, которая объясняет область видимости и разницу между областью определения glocal и локальным охватом с помощью ключевого слова wihtout var.

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

Когда значение присваивается переменной в javascript, интерпретатор сначала пытается найти "объявление переменной" в том же контексте/области, что и назначение. Когда интерпретатор выполняет dummyVariable = 20, он ищет декларацию dummyVariable в начале функции. (Так как все объявления Variable перемещаются в начало контекста с помощью javascript-интерпретатора, и это называется подъемом)

Вы также можете посмотреть подъем в javascript

0

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

См. ниже script в действии здесь, в jsfiddle

a = 1;// Defined outside the function without var
var b = 1;// Defined outside the function with var
alert("Starting outside of all functions... \n \n a, b defined but c, d not defined yet: \n a:" + a + "\n b:" + b + "\n \n (If I try to show the value of the undefined c or d, console.log would throw 'Uncaught ReferenceError: c is not defined' error and script would stop running!)");

function testVar1(){
    c = 1;// Defined inside the function without var
    var d = 1;// Defined inside the function with var
    alert("Now inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};


testVar1();
alert("Run the 1. function again...");
testVar1();

function testVar2(){
    var d = 1;// Defined inside the function with var
    alert("Now inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};

testVar2();

alert("Now outside of all functions... \n \n Final Values: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n You will not be able to see d here because then the value is requested, console.log would throw error 'Uncaught ReferenceError: d is not defined' and script would stop. \n ");
alert("**************\n Conclusion \n ************** \n \n 1. No matter declared with or without var (like a, b) if they get their value outside the function, they will preserve their value and also any other values that are added inside various functions through the script are preserved.\n 2. If the variable is declared without var inside a function (like c), it will act like the previous rule, it will preserve its value across all functions from now on. Either it got its first value in function testVar1() it still preserves the value and get additional value in function testVar2() \n 3. If the variable is declared with var inside a function only (like d in testVar1 or testVar2) it will will be undefined whenever the function ends. So it will be temporary variable in a function.");
alert("Now check console.log for the error when value d is requested next:");
alert(d);

Заключение

  • Независимо от того, объявлены с var или нет var (например, a, b), если они получают свое значение вне функции, они сохраняют свое значение, а также любые другие значения, которые добавляются внутри различных функций через script, сохраняются.
  • Если переменная объявлена ​​без var внутри функции (например, c), она будет действовать как предыдущее правило, она сохранит свое значение во всех функциях с этого момента. Либо он получил свое первое значение в функции testVar1(), он все еще сохраняет значение и получает дополнительное значение в функции testVar2()
  • Если переменная объявлена ​​с var внутри функции только (например, d в testVar1 или testVar2), она будет undefined всякий раз, когда заканчивается функция. Таким образом, это будет временная переменная в функции.
  • 0
    Спасибо, что нашли время, чтобы создать пример для демонстрации этой темы. В приведенном выше коде пропущена часть ниже, так что вы можете отредактировать свой ответ: a = 1; // Определено вне функции без var var b = 1; // Определено вне функции с помощью var alert («Запуск вне всех функций» ... \ n \ na, b определено, но c, d еще не определено: \ na: "+ a +" \ nb: "+ b +" \ n \ n (Если я пытаюсь показать значение неопределенного c или d, console.log выдаст ошибку «Uncaught ReferenceError: c не определено», и скрипт прекратит работу!) ");
0

Как кто-то пытается узнать это, я вижу это. Вышеприведенные примеры были, возможно, слишком сложными для новичка.

Если вы запустите этот код:

var local = true;
var global = true;


function test(){
  var local = false;
  var global = false;
  console.log(local)
  console.log(global)
}

test();

console.log(local);
console.log(global);

Результат будет считан как: false, false, true, true

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

var local = true;
var global = true;


function test(){
  local = false;
  global = false;
  console.log(local)
  console.log(global)
}

test();

console.log(local);
console.log(global);

Вывод: false, false, false, false

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

0

Без использования переменных "var" можно определить только при установке значения. В примере:

my_var;

не может работать в глобальной области или в любой другой области. Он должен быть со значением вроде:

my_var = "value";

С другой стороны, вы можете определить vaiable like;

var my_var;

Его значение undefined (его значение не null и оно не равно null).

  • 0
    my_var; на самом деле является действительным выражением выражения.
  • 0
    Это допустимое утверждение, если переменная определена ранее. В противном случае выдается ошибка «... не определено».
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню