12

I was handling a JavaScript file upload event. And I have the following initializer and the following function:

Initializer

    $('#s3-uploader').S3Uploader({
        allow_multiple_files: false,
        before_add: progressBar.show,
        progress_bar_target: $('.upload-progress-bar'),
        remove_completed_progress_bar: false
    }).bind("s3_upload_complete", function(e, content) {
        console.log(content);
    });

Function

var progressBar = {
    show: function() {
        $('.upload-progress-bar').show();
        return true;
    }
}

In the initializer, I noticed there is a difference if I do

before_add: progressBar.show v.s. before_add: progressBar.show(). With the parentheses, it will be called once even if it is bound to the before_add option, and without the parentheses it will not.

Is there an explanation for the behaviour I observed?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Chris Yeung
  • 2,613
  • 6
  • 34
  • 57
  • 2
    *With* parenthesis the method is invoked *because* of the parenthesis, the *result* of that invocation will be stored in before_add. *Without* the parenthesis you store a reference (or "pointer" if you will) to the function in the variable. **edit:** Added as [answer](http://stackoverflow.com/a/30751972/215042) which should be more appropriate. – RobIII Jun 10 '15 at 09:09
  • Does this answer your question? [In JavaScript, does it make a difference if I call a function with parentheses?](https://stackoverflow.com/questions/3246928/in-javascript-does-it-make-a-difference-if-i-call-a-function-with-parentheses) – Ivar Apr 23 '21 at 22:05

2 Answers2

22

With parentheses the method is invoked because of the parentheses, and the result of that invocation will be stored in before_add.

Without the parentheses you store a reference (or "pointer" if you will) to the function in the variable. That way it will be invoked whenever someone invokes before_add().

If that didn't clear things up, maybe this will help:

function Foo() {
    return 'Cool!';
}

function Bar(arg) {
    console.log(arg);
}

// Store the >>result of the invocation of the Foo function<< into X
var x = Foo();
console.log(x);

// Store >>a reference to the Bar function<< in y
var y = Bar;
// Invoke the referenced method
y('Woah!');

// Also, show what y is:
console.log(y);

// Now, try Bar **with** parentheses:
var z = Bar('Whut?');

// By now, 'Whut?' as already been output to the console; the below line will
// return undefined because the invocation of Bar() didn't return anything.
console.log(z);

If you then take a look at your browsers' console window you should see:

Cool!
Woah!
function Bar(arg)
Whut?
undefined

Line 1 is the result of invoking Foo(),
Line 2 is the result of invoking Bar() "via" y,
Line 3 is the "contents" of y,
Line 4 is the result of the var z = Bar('Whut?'); line; the Bar function is invoked,
Line 5 shows that invoking Bar() and assigning the result to z didn't return anything (thus: undefined).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
RobIII
  • 8,488
  • 2
  • 43
  • 93
4

Functions are first-class in JavaScript. This means they can be passed around, just like any other parameter or value. What you're seeing is the difference between passing a function and passing the value said function returns.

In your example:

before_add: progressBar.show

You want to pass progressBar.show instead of progressBar.show() because the former represents a function (function () {$('.upload-progress-bar').show(); return true;}) whereas the latter represents a returned result (true).

Here's another example:

// All this function does is call whatever function is passed to it
var callAnotherFunction = function (func) {
    return func()
}
// Returns 3 — that's all
var return3 = function () { return 3 }

// `callAnotherFunction` is passed `return3`
// so `callAnotherFunction` will `return return3()` === `return 3`
// so `3` is printed
document.write(callAnotherFunction(return3))

// `callAnotherFunction(return3())` is the same as `callAnotherFunction(3)`.
// This will print nothing because, in `callAnotherFunction`
// `func` is 3, not a function
// so it cannot be invoked, so nothing is returned
// and `document.write` doesn't print anything.
document.write(callAnotherFunction(return3()))
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
royhowie
  • 11,075
  • 14
  • 50
  • 67