Дополнительные круглые скобки для функции

Возможный дубликат:
Что означают круглые скобки, связанные с объявлением объекта/объекта/класса JavaScript?
Что это значит? (function() {}); ", функция внутри скобок, означает в javascript?
Функция Javascript

Я столкнулся с разметкой, подобной этой:

var something = (function(){
    //do stuff
    return stuff;
})()
document.ondblclick = function(e) { alert(something(e)) };

Я не понимаю открытие ( и закрываю )() в переменной something. Не могли бы вы объяснить разницу, чтобы написать это так?

var something = function(){
    //do stuff
    return stuff;
};

Спасибо!

Ответ 1

Вероятно, легче понять, оставите ли вы лишние парсеры, потому что они не имеют никакой цели:

var something = function() {
    return 3;
} // <-- a function. 
(); // now invoke it and the result is 3 (because the return value is 3) assigned to variable called something 

console.log(something) //3 because the function returned 3 

var something = function() {
    return 3;
}; // a function is assigned to a variable called something

console.log(something) //logs the function body because it was assigned to a function
console.log(something()) //invoke the function assigned to something, resulting in 3 being logged to the console because that what the function returns

Ответ 2

(function(){ ... }) является выражением функции (анонимное), вы можете, например, присвойте это значение переменной.

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

Когда stuff - это функция (которую я предполагаю, потому что вы вызываете something lateron), это называется закрытием - возвращаемая функция (stuff, назначенный something), все еще имеет доступ к переменным в контексте выполнения этой анонимной функции.

Ответ 3

На вопрос, что он делает, прочитайте все комментарии и другие ответы. Они абсолютно правы.

Почему вы хотите использовать его? Вы часто находите этот шаблон при использовании закрытий. Цель следующего фрагмента кода состоит в том, чтобы добавить обработчик события к 10 различным элементам DOM, и каждый должен предупредить его идентификатор (например, "Youve clicked 3" ). Вы должны знать, что если это было вашим фактическим намерением, гораздо более простой способ сделать это, но по академическим причинам вы можете придерживаться этой реализации.

var unorderedList = $( "ul" );
for (var i = 0; i < 10; i++) {
    $("<li />", {
        id: i,
        text: "Link " + i,
        click: function() {
            console.log("You've clicked " + i);
        }
    }).appendTo( unorderedList );
}

Вывод вышеуказанного кода может быть не таким, как вы ожидаете. Результатом каждого обработчика кликов будет "Youve clicked 9", потому что значение я в точке, в которой был запущен обработчик событий, равно "9". То, что действительно хочет разработчик, заключается в том, чтобы значение я отображалось в момент времени, когда обработчик события был определен.

Чтобы исправить эту ошибку, мы можем ввести замыкание.

var unorderedList = $( "ul" ), i;

for (i = 0; i < 10; i++) {
    $("<li />", {
        id: i,
        text: "Link " + i,
        click: function(index) {
            return function() {
                console.log("You've clicked " + index);
            }
        }(i)
    }).appendTo( unorderedList );
}

Вы можете выполнить и изменить приведенный выше код из jsFiddle.

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

Дальнейшее чтение закрытий: Использовать случаи для закрытия JavaScript

Ответ 4

Также проверьте раздел FAQ JavaScript: Вот несколько хороших объяснений и примеров

Хорошо, почему вы должны использовать это:

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

for(var i=0;i<nodesList.lenght;i++)
{
    if (nodesList[i].id==="theOneINeed")
    {
        aClosure = (function(node,indexInNodesList)//assign here
        {
            return function()
            {
                node.style.display = 'none';//usable after the parent function returns
                alert(indexInNodesList+ ' is now invisible');
            }
        })(nodesList[i],i);//pass the element and its index as arguments here
        break;
    }
}
i = 99999;
aClosure();//no arguments, but it'll still work, and say i was 15, even though I've just 
//assigned another value to i, it'll alert '15 is now invisible'

Что это позволяет мне сделать, это не допустить, чтобы аргументы функции были собраны в мусор. Обычно, после возвращения функции, все ее var и аргументы являются GC'd. Но в этом случае функция возвращает другую функцию, которая имеет ссылку на эти аргументы (она им нужна), поэтому они не GC'ed до тех пор, пока существует aClosure.

Как я уже сказал в своем комментарии. Google закрывает, немного тренируется, и это будет на вас рассвет... они действительно достаточно мощные

Ответ 5

Все ответы были хорошими, но я думаю, что самый простой ответ был снят:

var something = (function(){
    //do stuff
    return stuff;
})()

После выполнения этого кода something становится stuff. Функция, возвращающая материал, выполняется до того, как что-то назначено.

var something = function(){
    //do stuff
    return stuff;
};

После выполнения этого кода something есть функция, которая возвращает stuff. Функция, которая возвращает материал, никогда не выполнялась.