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?
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).
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()))
Related
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?
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).
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()))
If I wanted to first declare a function, and then at some point I want to reference the function and not its return value to a variable, how would I do that?
var best = bestPresidentEver;
function bestPresidentEver(a,b){
//for some reason always returns Trump.
}
and then call best(a,b) instead of bestPresidentEver(a,b)
I am wondering how to do that opposed to assigning the function to the var upon declaration.
var best =
function bestPresidentEver(a,b){
//for some reason always returns Trump.
}
Declare your variable like this
var bestPresidentEver= function (a,b){
//for some reason always returns Trump.
return "Trump"; //:D
}
Then call that function like this
//You have to declare a and b variables
var trumpHere = bestPresidentEver(a,b);
If your function is already declared, just assign it to the variable :
function bestPresidentEver (a,b){
//for some reason always returns Trump.
return "Trump"; //:D
}
var trumpHere = bestPresidentEver;
Then call it like this :
var trumpAgain = trumpHere(a, b);
If the variable exists and it's not a const you can simply reassign it's value to the function itself.
Ex
var foo = 'foo';
function bar(a) {
return 'example ' + a;
}
bar('code'); //=> "example code"
/* Further down, reassign the `foo` variable */
foo = bar;
foo('code, again'); //=> "example code, again"
I am using SignalR, and I need to point it to a function, and I also want to call that function in other areas of the application.
If the library expects a function parameter, you can simply pass that function like so.
function first(next /* expects a function parameter */) {
return next('hello');
}
function second(prefix) {
return prefix+ ' world!';
}
first(second); //=> "hello world!"
I just started reading Functional JavaScript and immediately was introduced to a function that I don't understand:
function splat(fun) {
return function(array) {
return fun.apply(null, array);
};
}
var addArrayElements = splat(function(x, y) { return x + y });
addArrayElements([1, 2]);
//=> 3
How does splat(function(x, y) { return x + y }) work. It's called with the array [1,2], but it seems like the anonymous function inside the call to splat takes two parameters, not one array.
Putting console.log(fun) on line 2 of this code shows that fun is the entirety of the anonymous function(x, y) { return x + y }. console.log(array) after return function(array) { shows that array is [1, 2]. Where does array come from then?
Thanks much.
It might be simpler to see how this function would have been written without using the .apply method:
function splat(fun) {
return function(array) {
return fun(array[0], array[1]);
};
}
First you call splat, passing it a function:
var add = function(x,y){ return x + 1 };
var ff = splat(add);
At this point, ff refers to the function(array) function, meaning its an one-argument function. The private variable fun refers to the add function.
Now, you call ff passing its one argument
ff([1,2]);
and it uses the values in the array to call fun with two arguments
return fun(array[0], array[1]);
The only difference between this and the real example is that the apply method lets you work with any argument array length instead of hardcoding a specific length (2) like I did.
//Every time we call this function, we get another one back
function splat(fun) {
return function(array) { // <-- this one will be returned in splat();
return fun.apply(null, array);
};
}
//Step one, call splat, pass a function as parameter
var addArrayElements = splat(function(x, y) { return x + y });
/*
Get back a function that accepts an array, and will execute the function we just passed in on it
*/
// This will call the newly created function, func will be available because it's in a closure
addArrayElements([1, 2]);
The last thing is that, even if the anonymous function takes two parameters, we call apply on it so it will bind array[0] ==> x and array[1] ==> y
This is an example of a higher order function. That's a function that takes functions as arguments and returns functions instead of just regular values (though functions are "just regular values" in Javascript). In this case:
function splat(fun) {
splat takes a function as its argument...
return function(array) {
...and returns a new function which takes an array...
return fun.apply(null, array);
...and when called calls the first fun function with the array .applied as its arguments.
So splat takes one function which expects several parameters and wraps it in a function which takes an array of parameters instead. The name "splat" comes from languages like Ruby, where a * (a "splat" or "squashed bug") in the parameter list of a function accumulates an arbitrary number of arguments into an array.
var addArrayElements = splat(function(x, y) { return x + y });
addArrayElements is now basically:
function (array) {
// closed over variable:
// var fun = function(x, y) { return x + y }
return fun.apply(null, array);
}
Here this is realized by a closure, which closes over and "preserves" the original fun passed to splat in the new returned function.
addArrayElements = function(array) { fun.apply(null, array); };
BUT
it has a closure whereby the variable context of its containing scope (that of the splat function that created the anonymous function) remains visible and accessible.
In JavaScript, functions are first-class objects that can be referenced and passed as arguments or, as in this case, through the closure mechanism.
Edit: about JavaScript and scope
In most languages, variables are, by default, local to the scope they're defined in (which usually is a function's local symbol table). By contrast, in JavaScript a variable is local only if it is defined using the var keyword; otherwise, the symbol will be looked back in the chain of the containing scopes, up to the implicit root object (which in the case of web browsers is window. I.e.,
function foo() { someVar = "bar"; }
foo();
alert(someVar); // shows "bar"
Not being restricted to the local scope, the symbol has been (purposely or not) leaked to the root scope.
Taking it one step further:
function foo() {
var baz = function() {
someVar = "bar";
};
baz();
}
foo();
alert(someVar); // shows "bar"
However, if you declare someVar within foo:
function foo() {
var someVar;
var baz = function() {
someVar = "bar";
};
baz();
alert("someVar in foo=" + someVar); // shows "bar"
}
foo();
alert("someVar in root=" + window.someVar); // shows "undefined"
Note that in this last version I needed to use window.someVar instead of just someVar because someVar never got defined as a variable in the root scope nor as a property of the root object, which caused an error.
a more functional approach uses bind(), which is short enough you don't really need splat anymore, and it's always nice to eliminate closures:
var addArrayElements = Function.apply.bind( function(x, y) { return x + y } , null );
addArrayElements([1, 2]); // === 3
so a simple example would be
function a() {
alert("something");
}
anything.onclick = a; // this is without parentheses
anything.onclick = a(); // this is with parentheses
What is the difference between the two?
And one thing more: if I define the same function but this time return false, will it work?
function a(){
alert("something");
return false;
}
The difference is that a() calls the function while a is the function.
console.log( a() ); // false
console.log( a ); // function() {...}
To make it clear what technically happens when you use the second part of your example, let's redefine alike this:
a = function() {
return 100;
};
and set the event handler:
anything.onclick = a();
f() not only calls the function f but returns its return value. So when setting a variable or object property to a function call, the return value of the function call will be assigned. So the above statement is effectlively equivalent to:
anything.onclick = 100;
which doesn't make sense and might cause an error. If a function doesn't have a return value, its return value is implicitly undefined.
However, if you had set a variable equal to a without calling it, it would be the same as setting a regular function expression to that variable:
var a = function() { ... },
b = a; // b = function() { ... }
b would perform the same operation as a would.
So in your example go with the first one because it makes sense! The only case in which you would assign the return value of the function call to an event handler is if the function returns another function. For instance:
var x = function(xyz) {
return function() {
console.log(xyz);
};
};
anything.onclick = x("Hello World"); // = function() {
// console.log("Hello World");
// }
Assigns reference:
anything.onclick = a; //assigns a reference
With your function it is:
anything.onclick = function() {
alert("something");
}
Executes method and assigns the returned result
anything.onclick = a(); //calls the method and assigns whatever is returned.
With your function it is:
anything.onclick = false;
The parenthesis at the end of the function is the permission for javascript engine to execute the function. If you don't supply it, it won't be executed at all.
If you do x=a() you are invoking the function but if you do x=a you are passing a pointer to a function
long story short:
Let's say we have
function f(){} or f = function(){}
If you now write
someFunction(f());
it will call f() and whatever f() returns will be passed as argument to someFunction().
If you write
someFunction(f);
on the other hand (when defined like the latter), f will be passed to someFunction() as (a variable holding) the function.
This could be used e.g. if the function is supposed to be used later on but maybe can't be called some other ('normal') way.
( Of course, depending on language, "function" could obviously be a "method" and the language could not even have function-variables or however you call it! )
( off topic: note that this answer says the same as the other answers because that is THE true answer but I did not want to edit the other answers because each may be found differently helpful by different people )
The following script produces "Hello", "undefined", "Hello" message boxes:
function action(callback) {
window.setTimeout(callback, 1000);
}
var obj = {
text: "Hello",
f: function() { window.alert(this.text); }
};
obj.f(); // Line 1
action(obj.f); // Line 2
action(function() { obj.f(); }); // Line 3
I looking for explanation why the line marked as "Line 2" produces "undefined" output.
in JavaScript, this is not bound to the method (like in python). Line 2 results in just the function being called, and this is undefined or not obj
When you call line2: You are only passing the function into the parameter. Since you are only passing the function, not the whole object, when it is called, this in the function does not refer to obj, thus making this.text undefined.
Alot of JS libraries do something like this:
if (!Function.prototype.context) {
Function.prototype.context = function (object) {
var fn = this;
return function () { return fn.apply(object, arguments); };
};
}
To be able to pass/bind this to a handler.
So in your case you can do smthg like this
action(obj.f.context(obj));
and receive your 'Hello'. And yes, this is a general way to do something you done in step 3.
The second one you pass a function with no scope so this becomes the highest object in the scope chain. The third way you create a closure and call f on the object directly which leaves this with the proper scope.