Определить локальную функцию в JavaScript: использовать var или нет?

Когда локальная (внутренняя) функция объявлена ​​в JavaScript, существует два варианта:

Объявление с помощью ключевого слова var, присваивающего переменной:

(function() {
    var innerFunction1 = function() { ... };
    innerFunction1();
}());

Объявление только с помощью ключевого слова function без назначения переменной:

(function() {
    function innerFunction2() { ... };
    innerFunction2();
}());

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

Какой из них лучше и почему?

Ответ 1

На самом деле существует 3 способа объявления функции:

  • Объявление функции: Объявление функции определяет именованную функциональную переменную без необходимости назначения переменных. Объявление функций происходит как автономные конструкции и не может быть вложено внутри не-функциональных блоков. ex: function innerFunction1 () { };

  • Выражение функции:: Функция Expression определяет функцию как часть синтаксиса большего выражения (обычно назначение переменной), Функции, определенные с помощью выражений функций, можно назвать или анонимными:

    а. Использование анонимной функции - var innerFunction1 = function() { };

    б. Использование названной функции - var innerFunction1 = function myInnerFunction () { };

  • Конструктор функций: Конструктор функций динамически определяет функцию с помощью конструктора Function(). Обратите внимание, что тело функции передается функции как строковый аргумент. var innerFunction1 = new Function (arg1, arg2, ... argN, functionBody)

Третий метод не рекомендуется, так как передача тела функции в виде строки может помешать некоторым оптимизации JS-движка и подвержена ошибкам.

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

Я использую выражение функции, где мне нужно

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

Некоторые отличия между объявлением функции и выражением функции:

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

Нажмите здесь, чтобы прочитать подробное сравнение объявления функции vs Function Expression vs Function Constructor @MDN p >

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

function foo() {}
alert(foo); // alerted string contains function name "foo"
var bar = foo;
alert(bar); // alerted string still contains function name "foo"

Подробнее:

Ответ 2

Две записи функционально эквивалентны.

Можно предположить, что:

function a() {}
function b() {}

интерпретируется как:

var a, b;
a = function a() {};
b = function b() {};

Вот почему вам не нужно объявлять (не определять!) перед использованием. Вы можете переназначить функции после того, как вы их определили, так же, как и с переменной. Функции поднимаются так же, как переменные, потому что они являются переменными (mind = blown? Good!).


Объявляет-до-использование

function a() { b(); } // using b before it declared?
function b() {}

становится:

var a, b;
a = function a() { b(); }; // nope! b is declared, we're good
b = function b() {};

Переопределение функции

function a() { alert("a"); }
a = function b() { alert("b"); }; // that weird!

становится:

var a;
a = function a() { alert("a"); };
a = function b() { alert("b"); }; // oh, that looks normal

Объявить vs define

Объявить: var x. На английском языке: "Я буду использовать переменную x".

Определить: x = 5. На английском языке "Переменная x теперь имеет значение 5".

Требуется объявление и использование в "use strict". Определить-до-использования не требуется. Если ваши переменные определены во время выполнения, вы хорошо.

Итак, var x = 5 является объявлением и определением, как есть function a() {}.

Будьте осторожны, если функции именования не перекрывают существующую переменную:

var a = function () { alert("a"); };
var b = function a() { alert("b"); };
a(); // prints "b"

Lint инструменты пойдут на это.


Когда использовать эту нотацию?

Я бы рекомендовал использовать обозначение выражения функции (var a = function () {}) только в том случае, если позже вы переназначаете значение a. Выражение функции затем сигнализирует читателю, что a будет переназначаться и что он намерен.

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

Редактировать заметки: Я немного пересмотрел анонимные функции. Может быть полезно называть анонимные функции, когда вы смотрите на стек. Именованная функция даст больше контекста, чтобы он не был зарегистрирован как "анонимный".

Ответ 3

Разница заключается в том, что функция с VAR определяется в время выполнения,

тогда как функция() без VAR определяется в время синтаксического анализа для блока script.

Это единственное существенное отличие.

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

Ответ 4

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

Есть только две реальные отличия.

1) Считываемость и предпочтения

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

2) Небольшая экономия места

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


Резюме

Все зависит от предпочтений. Что лучше? Кому ты рассказываешь. Лично я буду использовать var, если я намереваюсь сделать объект из него с помощью new, а затем запишу его в первую букву, например Person. В противном случае я склоняюсь к camelCase и опускаю использование var.

Ответ 5

  • var без имени функции

    • лучше, если вы освоите объявления переменных: особенно , когда они объявлены.


  • Функция с именем без var:

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


  • Функция с именем или без var

    • подходит для объявления класса,
    • и для профилирования, например, инструмент профилирования Chrome dev будет более явным, если функции не анонимны: у них будет явное имя, и вы узнаете, где медленная часть вашего кода.


  • Функция с именем и с var

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

Ответ 6

Локальные объявления всегда должны использовать var.

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

Существует также примечание к руководству по стилю google javascript, в котором говорится, что вторая форма не является частью стандарта, поэтому ее не следует использовать.

Объявления функций внутри блоков

Не делайте этого:

if (x) {function foo() {}} Хотя большинство script поддерживают двигатели Объявление функций внутри блоков не является частью ECMAScript (см. ECMA-262, пункты 13 и 14). Хуже реализации несовместимы друг с другом и с будущими предложениями EcmaScript. Только ECMAScript разрешает объявление функций в списке корневых операторов script или функции. Вместо этого используйте переменную, инициализированную с помощью функции Выражение для определения функции внутри блока:

if (x) {

var foo = function() {}

}

Источник http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml.

Ответ 7

Согласитесь с @MarmiK. Также разница между двумя методами - это область. Пока объявление функции назначает локальную область по умолчанию, область действия функции, назначенной переменной, зависит от области действия переменной.

var a;
(function() {
    var innerFunction1 = function() { ... };//local scope
    a=innerFunction1;//assigning to a global variable
}());

доступен глобальный доступ. Перейдите с объявлением функции, если вам не нужно изменять область действия. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope

EDIT:

var a;
(function() {
    function innerFunction1() { ... };//local scope
    a=innerFunction1;//It works too(Don't know why it should though)
}());

Итак, как указано в @Frits, похоже, нет никакого преимущества в использовании одного типа над другим.

Ответ 8

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

Это означает, что если ваш код завтра будет изменен другим человеком, которого вы не знаете в какой-то день, и это большой проект, который разработчик не может найти, где объявлена ​​функция, вы должны использовать объявление функции (i означает функцию x ( ) {}), или если вы сначала объявляете функции, вы можете использовать выражения.

Ответ 9

Я думаю, что все, кто начинает программировать в JavaScript, рано или поздно задают себе вопрос. Я бы переформулировал ваш вопрос:

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

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

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

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

Мои первые языки были Pascal, C, Fortran, С++ и т.д. Я использовал С# сейчас. Поэтому, когда я начал писать программы JavaScript, вначале я использовал свой существующий стиль написания программ с других языков. Позже я изменил стиль своего кода JavaScript, соответствующий специфике языка.

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

(function() {
    "use strict";
    var myFunc1 = function (x) {
            // body where I can use x and this
            alert("x=" + x + ", this.foo=" + this.foo);
        },
        localVar1 = {foo: "bar"};

    myFunc1.call(localVar1, 1);
}());

Я использую оператор функции очень редко, и только если я объявляю конструктор класса следующим образом:

(function() {
    "use strict";
    function MyClass(x) {
        // the code of constructor
        this.abc = x;
    }
    var myInstance = new MyClass("xyz");
    alert(myInstance.abc);
}());

Я пытаюсь никогда не использовать третью форму:

(function() {
    "use strict";
    var myFunc1 = function myFunc2(x) {
            ...
        };
    ...    
}());

где myFunc2 объявляются дополнительно к myFunc1. Реализация такой формы зависит от веб-браузера. Он имеет смысл, вероятно, в случае использования рекурсивных функций.

Ответ 10

Определение функции javascript

Как упоминалось Vega, существует 3 способа определения функции:

  • конструктор функций
  • Объявление функции
  • выражение функции

Конструктор Cons of Function:

Конструкторам функций требуется тело функции как строка, которая:

  • может помешать оптимизации JS-движка
  • делает синтаксис невероятно трудным для записи: нужно избегать специальных символов и некоторого другого безумия, см. ниже

    var foo = (new Function("var bar = \'FOO!\';\nreturn(function() {\n\talert(bar);\n});"))();

    foo(); // The segment "function() {\n\talert(bar);\n}" of the function body string is not re-parsed.

Объявление о недостатках функции:

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

Плюсы выражения функции:

Выражения функций проще:

  • вы "просто знаете", какой переменной присвоено
  • вы не можете вызывать/ссылаться на переменную, которой назначена функция до ее определения, что является последовательным поведением с остальными определениями javascript

Подробнее о: Преобразование деклараций функций в выражения функций

Опасность: как упоминалось в "Недостатке объявления функций", это может привести к возникновению многих проблем, ниже более подробная информация об этом.

Очень легко преобразовать объявления функций в выражения функций.

"Объявление функции перестает быть одним, когда оно: становится частью выражения, больше не является" исходным элементом "функции или самой script." Исходный элемент "является не вложенным в script или тело функции https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Examples_2

операторы функций

"подлежат подъему, это означает, что независимо от того, где размещена функция, она перемещается в верхнюю часть области, в которой она определена. Это ослабляет требование о том, чтобы функции были объявлены перед использованием, что Я думаю, что это приводит к неаккуратности, а также запрещает использование операторов функций в операторах if. Оказывается, большинство браузеров допускают операторы функций в операторах if, но они различаются в том, как это следует интерпретировать, что создает проблемы с переносимостью". - из книги: Javascript Хорошие части


Подробнее о выражениях функций

Синтаксис такой как:

 var varName = function [name]([param] [, param] [..., param]) {    /* function expression */
      statements
 }

Заметки о [name] (сразу после "функции" в синтаксисе):

  • Функция name может быть опущена, и в этом случае функция станет известной как анонимная функция.
  • "Имя функции не может быть изменено, а переменная, назначенная функции, может быть переназначена".
  • "Имя функции может использоваться только внутри тела функции"., вы можете использовать эту функцию, чтобы функция вызывала себя рекурсивно.

Затем, используя [name], вы можете делать странные/забавные вещи, такие как ниже. Обратите внимание: я не рекомендую это делать, если вы новичок в определениях функций.

var count = 0;

var varName = function funcName() {    /* function expression */
  console.log('count is: ' + count );
  if(count<1){
    count++;
    funcName();   /* calls function funcName another time  */
  }
};

varName();    // invokes function funcName via variable varName
funcName();   // throws an error as funcName is not reachable

см. живую демонстрацию на jsbin.com/gijamepesu/1/edit?js,console

Типичная реализация и использование будут такими, как показано ниже.

 var myCoolFunc = function ( username, firstName, lastName ) {    /* function expression */
      console.log('user ' + username + ' has the real full name ' + firstName + ' ' + lastName);
 }

 myCoolFunc();

Еще одно замечание: функциональные выражения можно сразу вызвать, а объявления vs-функций не могут. Эта функция используется в IIFE, подробнее о Какова цель обертывания всех файлов Javascript в анонимных функциях типа "(function() {...})()" ?


Ресурсы

Ответ 11

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

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