В JavaScript, имеет ли значение, если я вызываю функцию с круглыми скобками? - PullRequest
99 голосов
/ 14 июля 2010

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

window.onload = initAll();

и

window.onload = initAll;

Пожалуйста, объясните принцип, лежащий в основе.*

Ответы [ 5 ]

155 голосов
/ 14 июля 2010
window.onload = initAll();

Этот выполняет initAll() сразу и присваивает возвращаемое значение функции window.onload.Обычно это , а не , что вы хотите.initAll() пришлось бы возвращать функцию, чтобы это имело смысл.

window.onload = initAll;

это назначает фактическую функцию на window.onload - это возможно, потому чтов JavaScript, как говорит @Felix, функции - это объекты первого класса - без их выполнения.initAll будет выполнено событием загрузки.

133 голосов
/ 14 июля 2010

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

Я не буду использовать window.onloadпотому что это немного придумано, чтобы продемонстрировать.Вместо этого я буду использовать простую функцию умножения для демонстрации:

function Multiply(operator, operand) {
    return operator * operand;
}

Это также можно записать так:

Multiply = function(operator, operand) {
    return operator * operand;
}

Хотя в первом примере значение может быть неочевидным,Во втором примере более четко показано, что мы присваиваем функцию, имеющую 2 параметра, переменной с именем Multiply, и эта концепция функций как присваиваний распространена во всем JavaScript.Это небольшая демонстрация того факта, что функции являются «первоклассными гражданами» , то есть их можно передавать точно так же, как если бы мы передавали значения.

Итак, теперьразница в присваивании:

var operator = 3;
var operand = 4;
var ret = Multiply(operator, operand);

В точке определения переменной ret выполняется Multiply и присваивается возвращаемое значение - ret становится равным 12.

Давайте попробуемэто опять по-другому:

var operator = 3;
var operand = 4;
var ret = Multiply;

Теперь, в точке определения ret, ret становится вашей Multiply функцией, а не результатом, полученным от вашей функции Multiply.Вызов ret() вызовет выполнение вашей функции Multiply, и вы можете вызывать ее точно так же, как если бы вы вызывали Multiply(operator, operand):

var out = ret(3, 4);

- это то же самое, что

var out = Multiply(3, 4);

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

Возвращаемся к вашему window.onload.Думайте об этом как:

window.onload = function() {
    //Doing what all good window.onload functions should do...
}

initAll = function() {
    return 12;
}

Итак, как вы можете видеть, window.onload - это функция, как и любая другая функция, в этом нет ничего особенного.Вы можете присвоить ему значение, назначить ему функцию, обнулить ее, если хотите - дело в том, что в window.onload нет ничего более особенного, чем в вашей собственной функции.Единственное, что немного отличается, это то, что он вызывается окном при загрузке.[Отказ от ответственности: я никогда не отменял оконные функции, поэтому я не уверен, что это вызовет негативные последствия.Можно было бы надеяться, что они проверят, назначена ли функция перед ее вызовом, т.е. if (window.onload) window.onload();].

Теперь вызывается initAll(), что мы говорим:

window.onload = initAll();

, что можета также скажите:

window.onload = 12;

Но когда мы говорим initAll без скобок, мы на самом деле говорим: я хочу заменить любую мою функцию window.onload новой функцией - т.е.Я хочу заменить его на мою initAll функцию, чтобы при любых вызовах window.onload выполнялся мой initAll код.

Итак:

window.onload = function() {
    //Doing what all good window.onload functions should do...
}

заменяется на:

window.onload = function() {
    return 12;
}

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

На самом деле, вы могли бы одинаково написать:

window.onload = function() {
    //Write all your init code right in here instead of having a separate 
    //initAll function.
}

Еще один пример, который может продемонстрировать лучше, это:

var d = new Date();
var currentTime = d.getTime();

Независимо от того, какое время было в то время, как определено d, в конечном итоге присваивается currentTimeОтлично, но это полезно, только если мы хотим выяснить, во сколько была вызвана функция, содержащая этот код, то есть во время загрузки страницы.Что если мы хотим узнать текущее время в любое время, когда вызывается currentTime?

var currentTime = function() {
    var d = new Date();
    return d.getTime();
}

var a = currentTime(); //The current time at the point a is defined...
var b = currentTime;   //b is a functional reference to currentTime...
var c = b(); //The current time when variable c is defined
var d = c; //The current time when variable c was defined

Обратите внимание, как мы называем b() в наших c и d назначениях точно так же, как мы могли бы вызвать currentTime()

16 голосов
/ 14 июля 2010

Функции в javascript - это граждане первого класса, и поэтому их можно присваивать другим переменным или передавать в качестве аргументов.

Итак, когда вы делаете

window.onload = initAll;

установка свойства onload объекта window для ссылки на саму функцию initAll.

Когда вы делаете

window.onload = initAll();

Вы устанавливаете свойство onload для хранения возвращаемое значение для initAll, поскольку оно будет выполняться на месте в этой строке.

10 голосов
/ 14 июля 2010

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

Так что если вы сделаете что-то вроде

a = initAll

, тогда a станет таким же, как initAll - например, вы можете сделать a() - но с

a = initAll()

переменная a получит возвращаемое значение выполненной initAll функции

6 голосов
/ 14 июля 2016

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

Итак, вот TLDR ; или с высоты птичьего полета при вызове функций, использующих и не использующих () 's

Давайте возьмем эту функцию, например:

function foo(){
return 123;
}

если вы регистрируете "foo" - без ()

console.log(foo); 

---outout------
function foo(){
return 123;
}

Использование no () означает выборку самой функции . Это можно сделать, если вы хотите, чтобы он передавался как обратный вызов.


если вы регистрируете "foo ()" - с ()

console.log(foo());
-----output-----
 123

Использование () после функции означает выполнение функции, а возвращает ее значение .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...