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
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()))
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()))
Reading about functional programming - got to currying, example has a simple currying function. I understand everything except the last else block.
var curry = function (fn, fnLength) {
fnLength = fnLength || fn.length;
return function () {
var suppliedArgs = Array.prototype.slice.call(arguments);
if (suppliedArgs.length >= fn.length) {
return fn.apply(this, suppliedArgs);
} else if (!suppliedArgs.length) {
return fn;
} else {
return curry(fn.bind.apply(fn, [this].concat(suppliedArgs)), fnLength - suppliedArgs.length);
}
};
};
If the supplied args are >=, call the function with the supplied arguments.
Else if suppliedArgs.length is falsy, return the original function without doing anything.
Else ???
I think recursively call the function?
I don't understand what .bind.apply accomplishes.
Is [this] just in an array because suppliedArgs.push wouldn't return the array?
Start by looking at how you call Function#bind():
fun.bind(thisArg[, arg1[, arg2[, ...]]])
Then consider how you use Function#apply():
fun.apply(thisArg, [argsArray])
So given for bind() we need to call it on a function, and give it multiple parameters (not an array), and all we have is an array of arguments (suppliedArgs in the code), then how can we do that? Well, the main way you can call a function that takes multiple arguments instead of a single argument that is an array is to use .apply() on the function. So then we have fn.bind.apply(...something...).
The first parameter to .apply() is the this value - which needs to be the function to be bound in the case of .bind() (see below for an explanation of why). Hence fn.bind.apply(fn, ...).
Then, the second parameter to .apply() is an array of all the arguments to the function you are invoking, which in the case of .bind() is thisArg[, arg1[, arg2[, ...]]]. Hence we need a single array, with the first value being the value for this within the function, followed by the other arguments. Which is what [this].concat(suppliedArgs) produces.
So the whole fn.apply.bind(fn, [this].concat(suppliedArgs)) thing produces a correctly bound function that will have the supplied arguments to the current function "prefilled", with the correct this context. This function that is produced is then passed as the fn parameter in a recursive call to curry(), which in turn will produce another function in the same way as the top level call will.
The overall effect is that whenever you call a function created by curry(), if you don't pass the expected number of parameters, you will get a new function which takes the remaining number of parameters, or you will evaluate the original function with the entire list of parameters passed in correctly.
e.g.
function addAllNums(a, b, c, d, e) {
return a + b + c + d + e;
}
var curriedAddAll = curry(addAllNums, 5);
var f1 = curriedAddAll(1); // produces a function expecting 4 arguments
var f2 = f1(2, 3); // f2 is a function that expects 2 arguments
var f3 = f2(4); // f3 is a function that expects 1 argument
var f4 = f3(5); // f4 doesn't expect any arguments
var ans = f4(); // ans = 1 + 2 + 3 + 4 + 5 = 15.
// OR var ans = f3(5); => same result
Why the different thisArg values?
Probably the most confusing thing about this line of code is the two different values for thisArg in .bind() and .apply().
For .apply(), the thisArg is what you want the value of this to be inside the function you are calling .apply() on. e.g. myFunction.apply(myObj, ['param1', 'param2']) is equivalent to myObj.myFunction('param1', 'param2').
In this particular case, .bind() is executed on the fn function, so we want fn to be the this value for .bind(), so it knows what function it is creating a bound version of.
For .bind(), the thisArg is what the value of this will be inside the bound function that is returned.
In our case, we want to return a bound function that has the same this value as we currently have. In other words, we want to maintain the this value correctly within the new function, so it doesn't get lost as you create new functions which happens when you call a curried function with less arguments than it expects.
If we did not maintain the this value correctly, the following example wouldn't log the correct value of this. But by maintaining it, the correct value will be output.
var myObj = {
a: 1,
b: curry(function (a, b, c, d) {
console.log('this = ', this);
return a + b + c + d;
})
};
var c = myObj.b(1,1,1); // c is a function expecting 1 argument
c(1); // returns 4, and correctly logs "this = Object {a: 1, b: function}"
// if "this" wasn't maintained, it would log the value of "this" as
// the global window object.
The last else block is the main and most important part of the curry function, as it is the actual line that carries the logic for currying.
return curry(fn.bind.apply(fn, [this].concat(suppliedArgs)), fnLength - suppliedArgs.length);
This is what returns the new function that needs n-1 arguments from your previous function. Why? It's a combination of multiple things:
fn.bind.apply simply calls a function in the context of the function itself, while supplying the needed args (suppliedArgs). Note how the next parameter to curry is fnLength - suppliedArgs.length, which reduces the arguments needed to what was passed.
Let's explain it with the help of ES6. Things are going to become more obvious.
// Imagine we have the following code written in ES5
function fn(a, b, c) {
console.log(a, b, c);
}
var arr = [1, 2, 3];
var funcWithBoundArguments = fn.bind.apply(fn, [null].concat(arr));
Let's convert ES5 to ES6 code
// ES6
function fn(a, b, c) { console.log(a, b, c) }
let arr = [1,2,3];
let funcWithBoundArguments = fn.bind(null, ...arr)
You see? When you bind a function we have to explicitly enumerate all the arguments like:
fn.bind(null, 1, 2, 3)
But how could we bind the content of an array if we don't know its content in advance?
Right, we have to use .bind.apply() where:
the 1st argument of apply is the function (fn) we bind
the 2nd argument is an array which gets the context (as the first item of array) that we bind our function to and the rest of the items of the array are the arguments (which number is variable) we bind to our function (fn).
Using JavaScript, say I have a function X, and in that function an object called objectX is created. function X returns objectX. Later in the code function Z(somevar, anObject) receives objectX as one of it's parameters.
Now in function Z, is objectX and all its properties referred to as anObject inside function Z?
And what happens if function Z returns anObject? Will the rest of the code see the object as "objectX" or "anObject"?
function X() {
...
objectX = {};
...
return objectX;
}
X();
function Z(anything, anObject) {
...
return anObject
}
Z(something, objectX);
anObject and objectX both are referencing to the same space in memory, so, name it as you want, it's always the same object.
Good luck!
This is mostly a question of scope.
function X() {
// local objectX, only accessible through this name inside X()
var objectX = {};
objectX.foo = 'bar';
return objectX;
}
function Z(somevar, anObject) {
// anObject is passed in as a parameter
// it's only accessible through this name inside Z()
anObject.foo = somevar;
return anObject;
}
// get the 'objectX' from X() and store it in global variable a
var a = X();
// pass the received 'objectX' into Z()
// note that the variable names objectX and anObject cannot be accessed
// because they are local variables of the functions X() / Z()
var b = Z('baz', a);
// a is now the same as b, they both reference the same var
// a.foo and b.foo both are set to 'baz'
I believe an example is the best way to teach. Here is some code (click here to see it in JS Bin):
// Defines the variable to keep track of how many objects X() defines.
var num = 1;
// Instantiate another variable to see if it is changed by Z().
var anObject;
// Creates an object with a comment and a random number.
function X() {
// Create an object and give it a name.
var objectX = {comment : "Creation #" + num};
// Increase the value of num.
num++;
// Add another random number between 0 and 100 inclusively.
objectX.randNum = Math.round(Math.random() * 100);
// Return objectX.
return objectX;
}
// Modifies the second parameter by adding the value of the first parameter.
function Z(somevar, anObject) {
anObject.somevar = somevar;
return anObject;
}
var objectX = X(), objectY = X();
objectX2 = Z('coolness', objectX);
// Notice that objectX is still the result of calling X() the first time.
alert("objectX.comment = " + objectX.comment);
// Notice that objectX is not equal to objectY.
alert("objectX === objectY evaluates to " + (objectX === objectY));
// Notice that objectX2 is the same thing as objectX.
alert("objectX === objectX2 evaulates to " + (objectX === objectX2));
// Notice that anObject is not defined.
alert("typeof anObject evaluates to " + (typeof anObject) + " after Z is called.");
alert("Now review the JavaScript code.");
If read through the comments, you will find the answers to your questions. First you will notice that in function Z, since I passed objectX as the second parameter, inside of the function, it could be referred to by anObject. Second you will notice that once outside of function Z, anObject no longer refers to objectX. The comments also reveal other things that are true in JavaScript.
Javascript has function scope. This means that every variable declared within a function, will only be accessible from within that function.
If you’d properly declared the objectX variable with var, as follows:
function X() {
...
var objectX = {};
...
return objectX;
}
then objectX would only be known as objectX inside the X function. Elsewhere, it would be known as whatever variable you’d assigned it to. Since in your code, you don’t assign the result of X() to anything, objectX would not be accessible from anywhere.
However, here’s one of Javascript’s more serious design flaws: if you don’t explicitly declare a variable (using the var statement, or as a function parameter), that variable will automatically become a global variable. That means that it will be accessible anywhere.
Because of this, in your code above, you can access objectX everywhere by that name.
anObject, on the other hand, is properly declared (as a parameter), and that means its scope will be limited to the Z function.
In short, the way your code is written, objectX is accessible everywhere by way of the objectX variable, and inside the function Z, you can reference it both as objectX and as anObject.
Do note, however, that global variables are a Bad Thing™, since they can make it quite hard to figure out what variable gets assigned by who, when, and why — as you’ve noticed.
While Javascript makes it impossible to completely avoid them, as a rule you should try to keep the scope of your variables as small as possible (scope = where in your program that variable can be accessed).
To that end, I would recommend refactoring your code like igorw has.
Here is link to jsfiddle
Lets take the following example below:
Person = function(name){
this.name = name;
}
function x(){
var john = new Person('john');
return john;
}
function z(tempVar, anObject){
var newObj = anObject;
newObj.name = tempVar;
return newObj;
}
myPerson = x();
console.log(myPerson.name); //john
console.log(z('peter', myPerson).name); //peter
console.log(myPerson.name); //peter
You can see, even though you created a new object in z but because they are referencing to the same object myPerson's name property is also changed after z() is called.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}
What's the difference between:
function sum(x, y) {
return x+y;
}
// and
var sum = function (x, y) {
return x+y;
}
Why is one used over the other?
The first is known as a named function where the second is known as an anonymous function.
The key practical difference is in when you can use the sum function. For example:-
var z = sum(2, 3);
function sum(x, y) {
return x+y;
}
z is assigned 5 whereas this:-
var z = sum(2, 3);
var sum = function(x, y) {
return x+y;
}
Will fail since at the time the first line has executed the variable sum has not yet been assigned the function.
Named functions are parsed and assigned to their names before execution begins which is why a named function can be utilized in code that precedes its definition.
Variables assigned a function by code can clearly only be used as function once execution has proceeded past the assignment.
The first tends to be used for a few reasons:
The name "sum" shows up in the
stacktrace which makes debugging
easier in many browsers.
The name
"sum" can be used inside the
function body which makes it easier
to use for recursive functions.
function declarations are "hoisted"
in javascript, so in the first case,
the function is guaranteed to be
defined exactly once.
Semicolon insertion causes
var f = function (x) { return 4; }
(f)
to assign 4 to f.
There are a few caveats to keep in mind though.
Do not do
var sum = function sum(x, y) { ... };
on IE 6 since it will result in two function objects being created. Especially confusing if you do
var sum = function mySym(x, y) { ... };
According to the standard,
function sum(x, y) { ... }
cannot appear inside an if block or a loop body, so different interpreters will treat
if (0) {
function foo() { return 1; }
} else {
function foo() { return 2; }
}
return foo();
differently.
In this case, you should do
var foo;
if (0) {
foo = function () { return 1; }
} ...
The first one is a named function statement, the second one assigns an anonymous function expression to a variable.
The function statement is added to its scope immediately - you don't need to run it before being able to call it, so this works:
var y = sum(1, 2);
function sum(x, y) {
return x + y;
}
But the function expression is only assigned to the variable when the code is executed, so this doesn't work:
// Error here because the function hasn't been assigned to sum yet.
var y = sum(1, 2);
var sum = function(x, y) {
return x + y;
}
An advantage of the expression form is that you can use it to assign different functions to the expression at different points - so you can change the function, or use a different one under different conditions (such as depending on the browser being used).
An advantage of a named function statement, is that debuggers will be able to display the name. Although, you can name function expressions:
var sum = function sum(x, y) {
return x + y;
}
But this can be confusing since the two names are actually in different scopes and refer to different things.
The two code snippets you've posted there will, for almost all purposes, behave the same way.
However, the difference in behaviour is that with the second variant, that function can only be called after that point in the code.
With the first variant, the function is available to code that runs above where the function is declared.
This is because with the second variant, the function is assigned to the variable foo at run time. In the first, the function is assigned to that identifier foo at parse time.
More technical info
Javascript has three ways of defining functions.
Your first example is a function declaration. This uses the "function" statement to create a function. The function is made available at parse time and can be called anywhere in that scope. You can still store it in a variable or object property later.
Your second snippet shows a function expression. This involves using the "function" operator to create a function - the result of that operator can be stored in any variable or object property. The function expression is powerful that way. The function expression is often called an "anonymous function" because it does not have to have a name,
The third way of defining a function is the "Function()" constructor, which is not shown in your original post. It's not recommended to use this as it works the same way as eval(), which has its problems.
The difference is...
This is a nameless function
var sum = function (x, y) {
return x+y;
}
So if you alert(sum); you get "function (x, y) { return x + y; }" (nameless)
While this is a named function:
function sum(x, y) {
return x+y;
}
If you alert(sum); now you get "function sum(x, y) { return x + y; }" (name is sum)
Having named functions help if you are using a profiler because the profiler can tell you function sum's execution time...etcetera instead of an unknown functions's execution time...etcetera
here's an other example:
function sayHello(name) { alert('hello' + name) }
now,suppose you want modify onclick event of a button, such as it says "hello world"
you can not write:
yourBtn.onclik = sayHello('world'), because you must provide a function reference.
then you can use second form:
yourBtn.onclick = function() { sayHello('workld'); }
Ps: sorry for my bad english!
They mean the exact same thing. It's just syntactic sugar. The latter is IMO more revealing of what JavaScript is really doing; i.e. "sum" is just a variable, initialised with a function object, which can then be replaced by something else:
$ js
js> function sum(x,y) { return x+y; }
js> sum(1,2);
3
js> sum=3
3
js> sum(1,2);
typein:4: TypeError: sum is not a function
js> sum
3