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

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

window.onload = initAll();

и

window.onload = initAll;

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

98 голосов | спросил Dean 14 J000000Wednesday10 2010, 18:06:39

5 ответов


0
window.onload = initAll();

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

window.onload = initAll;

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

ответил Pekka 웃 14 J000000Wednesday10 2010, 18:09:08
0

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

Я не буду использовать 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()

ответил Pekka 웃 14 J000000Wednesday10 2010, 18:09:08
0

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

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

window.onload = initAll;

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

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

window.onload = initAll();

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

ответил Peter Bailey 14 J000000Wednesday10 2010, 18:11:26
0

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

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

a = initAll

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

a = initAll()

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

ответил Andris 14 J000000Wednesday10 2010, 18:10:09
0

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

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

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

function foo(){
return 123;
}

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

console.log(foo); 

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

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


если вы регистрируете "foo ()" - с помощью ()

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

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

ответил garrettmac 14 J000000Thursday16 2016, 03:43:19

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132