Один var на функцию в JavaScript?

Я использую JSLint, чтобы заставить себя чувствовать себя плохо из-за моего JavaScript. Между прочим, это здорово. Есть одна проверка, которую я не совсем понимаю, и мне хотелось бы узнать ваше мнение, пожалуйста.

С jslint.com:

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

Что на самом деле выделено жирным шрифтом в последнем послании? Я думаю, мне следует объявить несколько таких переменных?

var foo = 1, bar = 2;

И является ли «мудрая» частью всего лишь стилем программирования, призванным предотвратить ошибки в будущем, или это еще не все?

Спасибо за вашу помощь.


person Scott McKenzie    schedule 05.08.2009    source источник
comment
У меня было два превосходных ответа от stackoverflow.com/users/5445/cms и stackoverflow.com/users/51101/breton. Я чувствую, что они оба вместе отвечают на этот вопрос. Как я могу отдать должное обоим? :(   -  person Scott McKenzie    schedule 06.08.2009
comment
Кстати, если вы действительно хотите чувствовать себя плохо из-за своего кода, попробуйте прочитать исходный код в JSLINT и выяснить, как он работает. Он совершенно простой и читаемый, но все же загадочный. Это все равно, что узнать, что Вселенная - фрактал, рассчитанный по уравнению 2 + 2 =?   -  person Breton    schedule 06.08.2009
comment
Есть ли у кого-нибудь инструмент, который автоматически переформатирует код в одну переменную для каждого стиля функции? (но не уменьшать)   -  person jwl    schedule 02.06.2012
comment
У Ковбоя есть хороший контраргумент для нескольких выражений var (которые я теперь фанат): benalman.com/news/2012/05/multiple-var-statements-javascript   -  person RobW    schedule 16.05.2013


Ответы (4)


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

так что если у вас есть такая функция

var i = 5;
function testvar () {
     alert(i);
     var i=3;
}
testvar();

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

var i = 5;
function testvar () {
     var i;
     alert(i);
     i=3;
}
testvar();

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

person Breton    schedule 05.08.2009
comment
Интересно - я никогда не знал этого о JS - конечно, я все равно обычно определяю все свои переменные вверху и редко повторно использую имя переменной из внешнего цикла / функции. - person gnarf; 06.08.2009
comment
Это интересно, но на самом деле не связано с областью действия блока. - person Triptych; 06.08.2009
comment
Это не отвечает на часть вопроса, выделенную жирным шрифтом, а именно, почему рекомендуется только один оператор var. Это только объясняет причину того, почему операторы var должны появляться в начале функции. Есть идеи, почему рекомендуется только один? Мне любопытно, потому что, на мой взгляд, это негативно влияет на читабельность кода. - person Michael Lang; 27.05.2010
comment
@ Michael-Lang: Хорошо, я не могу сказать вам, как другие люди рационализируют это, но, со своей стороны, это заставляет меня использовать как можно меньше переменных, что является хорошим стилем кода. Если функция начинает иметь так много переменных, что вам нужно несколько операторов var, чтобы она была ясной, я бы сказал, что это запах кода (и я виноват!). Наличие одного оператора var рядом с параметрами также дает вам возможность увидеть все элементы, задействованные в функции, в одном месте. Размещение каждого на отдельной строке может быть менее четким и занимает место, которое минификатор не может сжать, и вы можете вставлять вещи между ними. - person Breton; 28.05.2010
comment
@ Michael-Lang ... вот еще немного идей Крокфорда: Р. Д. Теннент написал книгу под названием «Принципы языков программирования», в которой продемонстрировал принцип соответствия, который представлял собой соответствие между переменными и параметрами. JavaScript действительно хорошо это демонстрирует. Это показывает, что вы можете представить себе подмножество JavaScript, в котором не было переменных - будет ли это по-прежнему полезным языком? Оказывается, да, и это доказательство того, что все, что вы можете написать с помощью переменных, вы можете писать без переменных. Вместо этого вы можете использовать закрытие функции, чтобы сделать то же самое. - person Breton; 28.05.2010
comment
Объявление переменных в верхней части функции обычно затрудняет ручной рефакторинг. Вместо того, чтобы вырезать / вставить блок кода в новую функцию, вам нужно сделать это дважды, чтобы получить переменные. Это также часто приводит к тому, что разработчик оставляет неиспользуемые переменные по мере изменения кода (вне сайта, из памяти). Объявление в одном месте может позволить дополнительное сжатие с помощью чего-то вроде компилятора закрытия Google. Однако со временем такая оптимизация, вероятно, будет выполняться независимо от того, где объявлена ​​переменная. - person Richard Collette; 17.03.2011
comment
@ Michael-Lang - если вы предполагаете, что все объявления переменных будут в начале функции, тогда они могут быть выполнены с помощью одного оператора var, но я бы все равно поместил отдельные имена переменных в отдельные строки. Я считаю, что это легче читать, чем повторять var в каждой строке. (И наоборот, мне труднее читать объявления переменных, разделенных запятыми, в одной строке.) - person nnnnnn; 29.02.2012
comment
В ответе нужно больше точки с запятой ... :) - person Matt S; 02.05.2012
comment
@Breton: Под капотом находится var foo = 1, bar = 2; то же, что и var foo = 1; var bar = 2; - person Doug; 14.09.2014

В основном в блоках JavaScript ({ ... }) не вводят новую область видимости, есть только область видимости функции, поэтому никакая область не создается ни для одного другого оператора.

Переменная, введенная в любом месте функции, видна везде в функции.

Например:

function myFunction(){
  var one = 1;

  if (one){
    var two = one + 1;
  }

  (function () {
    var three = one + two;
  })();

  // at this point both variables *one* and *two* are accessible but 
  // the variable *three* was declared in the scope of a inner function
  // and is not accessible  at this point.
}

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

Прочтите эту статью.

person Christian C. Salvadó    schedule 05.08.2009
comment
Вы действительно не объясняете, почему так лучше. В конечном итоге из области видимости только функции следует, что лучше, чтобы вары были наверху. Но вы упустили рассуждения от этого факта до вашего заключения. - person Breton; 06.08.2009
comment
Я только что прочитал статью, на которую вы ссылаетесь, и она совершает ту же ошибку, что и Четан. повторное объявление var - это NOOP. Это совершенно безвредно и не вызывает никаких проблем. Нельзя сказать, что ограничиваться одним оператором var бесполезно, но вы, ни статья, на самом деле убедительно доказали это. - person Breton; 06.08.2009
comment
@Breton, это может вызвать проблемы, потому что часто это отражение сбитого с толку программиста. Это также может сбить с толку других программистов, которые поступают разумно и ставят все переменные в начало функции. - person Nosredna; 06.08.2009
comment
Если это рассуждение, то оно должно быть в исходном ответе. В нынешнем виде это похоже на силлогизм, в котором отсутствует вторая посылка. - person Breton; 06.08.2009
comment
Котята пушистые и маленькие. Поэтому котята милые. (Как бы правдиво это ни было, это неверный аргумент, потому что вы пропустили все пушистые и милые мелочи) - person Breton; 06.08.2009

Отсутствие области видимости блока объясняет приведенный ниже код:

var a = 1;
if (something) {
    var a = 2;
}

alert(a); // Alerts "2"

В большинстве языков C-стиля (как и в синтаксисе) определение var a = 2 будет определять 'a' только для области видимости блока if. Использование единственного оператора var в верхней части функции помогает избежать этой странности Javascript, которая не всегда так очевидна, как приведенная выше, и была бы неожиданной для программистов C / C # / Java.

person Triptych    schedule 06.08.2009

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

Причина объяснена в упомянутом вами абзаце. Переменные Javascript имеют только область функционального уровня. Если вы объявите ту же переменную внутри блока if / while / for, она будет перезаписана новым значением, поскольку блок не имеет новой области видимости. Это отличается от таких языков, как Java. Чтобы избежать таких сюрпризов, объявите все переменные, которые вы собираетесь использовать в функции, в начале функции, чтобы случайно не «повторно объявить» и все такое.

person Chetan S    schedule 05.08.2009
comment
Я не думаю, что проблема заключается в повторном объявлении переменной. Это не вызывает ошибки, как в C (или java?). Фактически это ничего не делает. - person Breton; 06.08.2009
comment
Извините, я должен был быть более ясным. Я имел в виду объявление того же имени переменной внутри блока, что разрешено в Java. Эта новая переменная живет только внутри блока. - person Chetan S; 06.08.2009
comment
Ах да, я полагаю, это было бы проблемой, если бы вы привыкли к языку с блочной областью видимости. - person Breton; 06.08.2009
comment
Мои навыки понимания прочитанного сегодня дерьмо. Я совершенно неправильно понял ваш исходный пост. - person Breton; 06.08.2009
comment
Нет проблем, я мог бы лучше сформулировать свой ответ. - person Chetan S; 06.08.2009