Я заметил разницу при вызове функции с пустыми круглыми скобками или вообще без скобок. Однако я не передаю в функцию никаких аргументов, поэтому мне стало интересно, в чем разница между:
window.onload = initAll();
и
window.onload = initAll;
Пожалуйста, объясните принцип, лежащий в основе этого.
javascript
Декан
источник
источник
(
ЛЕВАЯ скобка = открывающая скобка (1.0) и 0029)
Правая скобка = закрывающая скобка (1.0) - unicode.org/charts/charindex.html#P и что Dictionary.com говорит об этом - dictionary.reference.com/ browse / PARENTHESIS «Одна или обе прямые изогнутые линии, () ...»{}
называются беличьими скобками.Ответы:
Это исполняет
initAll()
сразу и присваивает возвращаемого функцией значения вwindow.onload
. Обычно это не то, что вам нужно.initAll()
должен был бы вернуть функцию, чтобы это имело смысл.это Назначает фактическая функция к
window.onload
- это возможно потому , что в JavaScript, как говорит @Felix функции являются объектами первого класса - без его выполнения.initAll
будет выполняться событием загрузки.источник
То, что говорит Пекка, правильно, но я хочу немного уточнить пример, который поможет объяснить кому-то, кто не полностью понимает указатели на функции или делегаты.
Я не буду использовать,
window.onload
потому что это немного надумано продемонстрировать. Вместо этого я воспользуюсь простой функцией умножения для демонстрации:Это также можно было бы написать:
Хотя в первом примере значение может быть неочевидным, второй пример более четко показывает, что мы назначаем функцию, которая имеет 2 параметра, переменной с именем
Multiply
, и эта концепция функций как присваиваний распространена во всем JavaScript. Это небольшая демонстрация того факта, что функции являются «гражданами первого класса» , то есть их можно передавать точно так же, как если бы мы передавали значения.Итак, теперь о различиях в назначении:
В момент определения переменной ret
Multiply
выполняется и присваивается возвращаемое значение -ret
становится равным 12.Попробуем еще раз по-другому:
Теперь, в момент определения
ret
,ret
становится вашейMultiply
функцией, а не результатом, полученным от вашейMultiply
функции. Вызовы вret()
вызовут выполнение вашейMultiply
функции, и вы можете вызвать ее точно так же, как если бы вы вызвалиMultiply(operator, operand)
:такой же как
Вы фактически сказали, что собираетесь использовать
ret
в качестве делегата дляMultiply()
. При вызовеret
мы действительно имеем в видуMultiply
функцию.Вернемся к вашему
window.onload
. Думайте об этом как:Как видите,
window.onload
это функция, как и любая другая функция, в ней нет ничего особенного. Вы можете присвоить ему значение, назначить ему функцию, обнулить, если хотите - дело в том, что нет ничего более особенного,window.onload
чем ваша собственная функция. Единственное немного другое - это то, что он вызывается окном при загрузке. [Отказ от ответственности: я никогда не отменял оконные функции, поэтому я не уверен, что это приведет к негативным последствиям. Можно было бы надеяться, что они проверят, назначена ли функция перед ее вызовом, т.е.if (window.onload) window.onload();
].Теперь называем
initAll()
то, что мы говорим:который также мог бы сказать:
Но когда мы говорим
initAll
без круглых скобок, на самом деле мы говорим следующее: я хочу заменить любую мою функцию window.onload новой функцией, то есть я хочу заменить ее своейinitAll
функцией, чтобы при любых вызовах выполнялисьwindow.onload
моиinitAll
код.Так:
заменяется на:
Таким образом, любой вызов
window.onload
будет выполнять вашуinitAll
функцию вместо того, чтоwindow.onload
было изначально. Вы заменили исходную функцию на новую.Фактически, вы могли бы написать:
Другой пример, который может лучше продемонстрировать:
Независимо от того, какое время было в то время
d
, определено, в конечном итоге назначеноcurrentTime
. Отлично, но это полезно только в том случае, если мы хотим узнать, в какое время была вызвана функция, содержащая этот код, то есть во время загрузки страницы. Что, если нам нужно текущее время в любое время, котороеcurrentTime
вызывается?Обратите внимание , как мы называем
b()
в нашихc
иd
присвоений точно так , как мы могли бы назватьcurrentTime()
?источник
Функции в javascript являются первоклассными гражданами и, как таковые, могут быть назначены другим переменным или переданы в качестве аргументов.
Итак, когда вы это сделаете
Вы устанавливаете
onload
свойствоwindow
объекта для ссылки наinitAll
саму функцию.Когда ты делаешь
Вы устанавливаете
onload
свойство для хранения возвращаемого значения initAll, поскольку оно будет выполняться на месте в этой строке.источник
initAll
- это ссылка на значение функции и оператор скобок, добавленный к имени функции. ЗАПУСКАЕТ этот объект функции.Итак, если вы сделаете что-то вроде
тогда
a
станет таким же, какinitAll
- например, вы можете сделатьa()
- но спеременная
a
получит возвращаемое значение выполненнойinitAll
функцииисточник
Я опоздал на 6 лет, но мне кажется, что это можно было бы объяснить намного проще, чем приведенные выше ответы.
Итак, вот TLDR ; или птичьего полета при вызове функции с использованием и без использования
()
«SВозьмем, к примеру, эту функцию:
если вы войдете в "foo" - без
()
Не использовать никаких
()
средств для получения самой функции . Вы бы сделали это, если хотите, чтобы это передавалось как обратный вызов.если вы зарегистрируете "foo ()" - с
()
Использование
()
после функции означает выполнение функции и возврат ее значения .источник