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

ПРИМЕЧАНИЕ. Этот вопрос был задан с точки зрения 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;

?

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

18 ответов

Решение

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

Если вы находитесь в функции, то 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

Есть разница

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. Основанием для этого было отловить случайные присваивания, предотвращающие создание нежелательных глобальных свойств. Некоторые из новых браузеров уже начали активную поддержку строгого режима. Смотрите, например, мою таблицу сравнения.

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

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

/* 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;
    }
}

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

with (window) {
    //Your code
}

Больше информации о with - MDN

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

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

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

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

РЕДАКТИРОВАТЬ: После того, как я получил критику, я хотел бы подчеркнуть следующее:

  • var объявляет переменную в текущей области видимости
  • Глобальный охват window
  • Не используется var неявно заявляет var в глобальной области видимости (окно)
  • Объявление переменной в глобальной области видимости (окна) с помощью var это то же самое, что опустить его.
  • Объявление переменной в областях, отличных от окна, используя var это не то же самое, что объявить переменную без var
  • Всегда объявлять var явно, потому что это хорошая практика

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

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

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

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

<script>
one();

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

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

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

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

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

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

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

Не использовать var!

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

использование const а также let

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

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

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

Другое отличие, например

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

в то время как

a = a || [] ; // a is undefined error.

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

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

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

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

@Chris S привел хороший пример, демонстрирующий практическую разницу (и опасность) между var и нет 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)})
})

Используя let однако:

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)})
})

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

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's 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

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

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

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);

Вывод будет выглядеть как: ложь, ложь, правда, правда

Потому что он видит переменные в функции отдельно от тех, которые находятся за ее пределами, отсюда термин локальная переменная, и это было потому, что мы использовали 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.

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

Смотрите скрипт ниже в действии здесь на 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);

Заключение

  1. Независимо от того, объявлено ли с var или без него (например, a, b), если они получат свое значение вне функции, они сохранят свое значение, а также будут сохранены любые другие значения, которые добавляются в различные функции через скрипт.
  2. Если переменная объявлена ​​без var внутри функции (например, c), она будет действовать как предыдущее правило, теперь она будет сохранять свое значение во всех функциях. Либо он получил свое первое значение в функции testVar1(), но все равно сохраняет значение и получает дополнительное значение в функции testVar2().
  3. Если переменная объявлена ​​с помощью var только внутри функции (как d в testVar1 или testVar2), она будет неопределенной при каждом завершении функции. Так что это будет временная переменная в функции.

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

console.log(noErrorCase);
var noErrorCase = "you will reach that point";

console.log(runTimeError);
runTimeError = "you won't reach that point";

Внутри кода вы, если вы используете переменную без использования 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 */
}

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

my_var;

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

my_var = "value";

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

var my_var;

Его ценность undefined (Его значение не null и это не равно null что интересно.).

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

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

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

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

Другие вопросы по тегам