Чи має значення в JavaScript, якщо я викликаю функцію з дужками?


105

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

window.onload = initAll();

і

window.onload = initAll;

Поясніть, будь ласка, принцип, що стоїть за цим.


24
@JS Bangs - лише англійською мовою США; не в іншому місці. Хоча програмісти, як правило, називають їх «круглими дужками», щоб уникнути плутанини, у британській англійській мові округлі називають просто дужками. Квадратні називають «квадратними дужками». en.wikipedia.org/wiki/Bracket
Роб Левін

13
на серйозну ноту, офіційна назва UNICODE - Parenthesis. 0028 ( ЛІВНІЙ ПАРЕНТЕЗ = відкриваюча дужка (1.0) та 0029 ) ПРАВИЙ ПАРЕНТЕЗ = закриваюча дужка (1.0) - unicode.org/charts/charindex.html#P і що Dictionary.com має про це сказати - dictionary.reference.com/ переглянути / PARENTHESIS " Либо або обидві вертикально вигнуті лінії, () ..."

8
Отже, це не просто "американська англійська" річ, це міжнародне стандартне визначення, оскільки UNICODE - це міжнародний стандарт.

2
@fuzzy - звідки ви серйозно берете свої факти? {}називаються дужками білки.
Анураг

7
@fuzzy lollipop - Unicode - це міжнародний стандарт кодування символів як байтів, а не імен. Автори документа Unicode не стверджують, що вказане ім'я для символу є міжнародним стандартом. Це код, порівняно з символом, який вони визначають. Але, можливо, ви хочете зауважити, що вони також відносять до [і] як квадратні дужки - (а не лише "дужки"), і що вони посилаються на всі [, {і (як символи, що дужки. Ви повинні прагнути зрозуміти нюанси). у різних місцях вживаються одні й ті самі слова. Дуже важливо, якщо ви є членом міжнародної команди.
Роб Левін

Відповіді:


161
window.onload = initAll();

Це виконує initAll() відразу і привласнює повертається функцією значення в window.onload. Зазвичай це не те, що ти хочеш. initAll()доведеться повернути функцію для цього, щоб мати сенс.

window.onload = initAll;

це Призначає фактична функція до window.onload- це можливо тому , що в JavaScript, як каже @Felix функції є об'єктами першого класу - без його виконання. initAllбуде виконано подією завантаження.


18
Тут важливо зазначити, що функції - це об'єкти першого класу в JavaScript.
Фелікс Клінг

136

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

Я не буду використовувати, 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

Функції javascript - це громадяни першого класу, і тому вони можуть бути віднесені до інших змінних або передаватися як аргументи.

Отже, коли ви робите

window.onload = initAll;

Ви встановлюєте onloadвластивість windowоб'єкта посилатися на initAllсаму функцію.

Коли ви робите

window.onload = initAll();

Ви встановлюєте onloadвластивість зберігати повернене значення initAll, оскільки воно буде виконуватися на місці в цьому рядку.


10

initAll є посиланням на значення функції, і оператор дужок додається до імені функції RUNS цього об'єкта функції.

Тож якщо ти робиш щось подібне

a = initAll

тоді aстане тим самим, що initAll- наприклад, ви можете зробити a()- але з

a = initAll()

змінна aотримає повернене значення виконаної initAllфункції


8

Мені запізнюється на 6 років, але я вважаю, що це можна було б пояснити набагато простіше, ніж наведені вище відповіді.

Так ось TLDR ; або погляд з пташиного польоту під час виклику функцій із використанням, а не з використанням ()'s

Давайте візьмемо для прикладу цю функцію:

function foo(){
return 123;
}

якщо увійти "foo" - без ()

console.log(foo); 

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

Не використовуючи ніяких ()засобів для отримання самої функції . Ви зробите це, якщо хочете, щоб це було передано як зворотний дзвінок.


якщо увійти "foo ()" - з ()

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

Використання ()після функції означає виконання функції та повернення її значення .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.