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

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

window.onload = initAll();

и

window.onload = initAll;

Объясните принцип позади него.

102
задан Cœur 19 August 2017 в 13:33
поделиться

4 ответа

 window.onload = initAll ();

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

 window.onload = initAll;

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

157
ответ дан 24 November 2019 в 04:25
поделиться

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

Поэтому, когда вы делаете

window.onload = initAll;

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

Когда вы это сделаете,

window.onload = initAll();

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

16
ответ дан 24 November 2019 в 04:25
поделиться

initAll - это ссылка на значение функции, и оператор скобок, добавленный к имени функции, ЗАПУСКАЕТ этот объект функции.

Итак, если вы выполните что-то вроде

a = initAll

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

a = initAll()

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

10
ответ дан 24 November 2019 в 04:25
поделиться

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

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

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

С тем же успехом можно написать:

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

Если в первом примере подтекст может быть неочевиден, то второй пример показывает более четко, что мы присваиваем функцию с двумя параметрами переменной 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()?

.
135
ответ дан 24 November 2019 в 04:25
поделиться
Другие вопросы по тегам:

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