Объявление функции JavaScript, которая находится внутри переменной? - PullRequest
4 голосов
/ 13 ноября 2011

Я читаю этот урок: http://nathansjslessons.appspot.com/

Внутри есть уроки, которые говорят:

// A simple function that adds one
var plusOne = function (x) {
    return x + 1;
};

Я привык видеть такие функции:

function myFunction() {
    return x + 1;
};

В чем разница между первым и вторым?

Ответы [ 5 ]

5 голосов
/ 13 ноября 2011

Разница только в первой функции:

var plusOne = function (x) {
    return x + 1;
};

определяется во время выполнения, тогда как другая функция:

function myFunction() {
    return x + 1;
};

определяется во время разбора для блока скрипта.

2 голосов
/ 13 ноября 2011

Прочтите сообщение , написанное @ CMS .Он прекрасно объясняет разницу между FunctionDeclaration и FunctionExpression.Чтобы процитировать то, что он написал:

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

1- Функция, определенная с помощью Функция конструктор, назначенный переменной multiply :

  var multiply = new Function("x", "y", "return x * y;");

2- Объявление функции с именем multiply :

  function multiply(x, y) {
     return x * y;
  }

3- Выражение функции, назначенное переменной multiply :

  var multiply = function (x, y) {
     return x * y;
  };

4- Выражение именованной функции func_name , назначенное переменной multiply:

  var multiply = function func_name(x, y) {
     return x * y;
  };

Проще говоря, следующий код может быть FunctionDeclaration или FunctionExpression в зависимости отконтекст:

function foo() {}

Выше FunctionDeclaration.

0, function foo() {}

Выше FunctionExpression.Разница между ними более подробно объясняется @CMS в его вышеупомянутом ответе.

По вашему вопросу:

// A simple function that adds one
var plusOne = function (x) {   // a function expression is assigned to a variable
    return x + 1;
};

function myFunction() {        // a simple function declaration
    return x + 1;
};
1 голос
/ 13 ноября 2011

Они делают почти одно и то же, но есть различия и причины для того и другого. Первое выражение функции, потому что оно назначено переменной. Кроме того, это не относится к выражению функции, это анонимная функция, потому что у нее нет имени функции. Второе - это объявление функции, потому что оно не является частью другого выражения и является «элементом источника (не вложенная инструкция в скрипте или функция тела) функции скрипта». (Я не совсем знаю, как объяснить исходный элемент, поэтому я скопировал это из документации Mozilla). У этого также есть имя функции, myFunction. Кроме того, функция может также использоваться перед объявлением функции, в отличие от функций, определенных выражением функции.

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

plusOne(1);
var plusOne = function (x) {
    return x + 1;
};

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

plusOne(1);
function plusOne(x) {
    return x + 1;
};

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

Предполагая, что у вас достаточно базовых знаний javascript (для циклов, создания и добавления элементов dom и onclick), возьмите, например, следующий код, который похож на проблему, с которой я столкнулся до того, как обнаружил замыкания самостоятельно. Прочтите его, не запуская сначала код, и попытайтесь выяснить, что произойдет, когда вы нажмете каждую кнопку / div.

function addButtons() {
    for (var i=0; i<3; i++) {
        button = document.createElement("div");
        button.innerHTML = "Button " + i;
        button.onclick = function () {
            alert(i);
        };
        document.body.appendChild(button);
    }
}
addButtons();

Можно ожидать, что кнопка 1 выдаст предупреждение «1», а кнопка 2 выдаст предупреждение «2», а кнопка 3 выдаст предупреждение «3». Однако, что происходит, все кнопки будут предупреждать «3». Это связано с тем, что onclick не выполняется до тех пор, пока переменная i не будет увеличена до 3.

Теперь прочитайте следующий бит кода. Поначалу это может показаться немного запутанным.

function addButtons() {
    for (var i=0; i<3; i++) {
        var button = document.createElement("div");
        button.innerHTML = "Button " + i;
        button.onclick = function (j) {
            return function () {
                alert(j);
            }
        }(i);
        document.body.appendChild(button);
    }
}
addButtons();

Если вы запустите его, вы увидите, что каждая кнопка оповещает о том, что вы, вероятно, ожидали, что они произойдут в первую очередь. Кнопка 1 выдаст предупреждение «1», кнопка 2 выдаст предупреждение «2», а кнопка 3 выдаст предупреждение «3». Итак, onlick возвращает замыкание, ссылающееся на j, которое устанавливается с i во время цикла for. Переменная j надежно хранится в замыкании, в отличие от i, которая меняется в каждом цикле. И, конечно, вы можете по-прежнему называть функции, используемые в замыкании, если хотите, но для этого нет причин.

Я не уверен, что объяснил это отлично, но я надеюсь, что это, по крайней мере, введение в нечто новое и полезное! Кроме того, вы можете найти гораздо больше информации о функциях в Mozilla Developer Network .

1 голос
/ 13 ноября 2011

в конце. нет разницы между 2. Просто разница в декларации.

0 голосов
/ 13 ноября 2011
var plusOne = function (x) {
    return x + 1;
};

является оператором переменной, инициализатором которого является выражение функции, тогда как

function plusTwo(x) {
    return x + 2;
}

- это объявление функции.

Чтобы понять разницу между ними, вам нужно понять, как инициализируются переменные:

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

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

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

Это не относится к объявлениям функций: объявления функций оцениваются во время привязки объявлений, т. Е. Перед общим выполнением кода.

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

alert(plusTwo(42));
function plusTwo(x) {
    return x + 2;
};
1020 * * * тогда * тысяча двадцать-одна
alert(plusOne(42));
var plusOne = function (x) {
    return x + 1;
};

потерпит неудачу, поскольку это концептуально эквивалентно

var plusOne = undefined;
alert(plusOne(42));
plusOne = function (x) {
    return x + 1;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...