Related
I'm new to functional programming and I'm trying to learn it in javascript. I found some examples and wrote my own snippet, but I don't understand WHY it works. There is a function called whatTheHeckIsThis. Can someone tell me what it is doing or what its purpose is? Note that when running this code, the output is true.
function boolFlipper(someFn){
return function whatTheHeckIsThis(x,y){
return !someFn(x,y);
};
}
var checkStrings = function(x, y){
return x === y;
}
var flipperTester = boolFlipper(checkStrings);
var str1 = "this string";
var str2 = "that string";
console.log(flipperTester(str1, str2));
My confusion is why can't I just do this instead:
function boolFlipper(someFn){
return !someFn(x,y);
}
a reference to whatTheHeckIsthis() will be returned and stored into flipperTester
After this, flipperTester can be used like a function.
You can use this language feature to abstract some code.
Simple example:
function addTen(x) { return x + 10 }
function multiplyByTen(x) { return x * 10 }
...
var doMath
// somewhere a user selected something
if (userInputSaysAdd) doMath = addTen
if (userInputSaysMultiply) doMath = multiplyByTen
// this will be the choosen function
doMath(someValue)
Your second version doesn't work for 2 reasons:
The purpose of boolFlipper is to return a new function, which you can assign to another variable and later call.
Your function doesn't have x and y parameters.
To solve #2 you could write:
function boolFlipper(someFn, x, y) {
return !someFn(x, y);
}
You would then have to call it like:
console.log(boolFlipper(checkStrings, str1, str2));
But you still couldn't do:
flipperTester = boolFlipper(checkStrings);
The original snippet returns a closure, which is bound in the environment where someFn is equal to the function passed as an argument to bookFlipper(). You can then assign this function to a variable, and call it with new arguments, that are assigned to x and y, and then the the function saved in someFn() is called, the return value is negated with !, and this is returned.
For more information about closures, see How do JavaScript closures work?
In JavaScript functions are objects, so you can return them. When you return a function you are getting a function object, so you can call it as any other function. For example:
function myFun() {
return function() {
console.log("test");
};
}
var functionInside = myFun();
/* This is like doing:
var functionInside = function() {
console.log("test");
};
*/
functionInside(); // This will execute the function.
Example with your code:
This variable:
var flipperTester = boolFlipper(checkStrings);
contains a function like this:
var flipperTester = function (x,y) {
return !someFn(x,y);
}
And this is something similar to
function flipperTester(x,y) {
return !someFn(x,y);
}
So when you do:
flipperTester(str1, str2)
You are executing that function. The variable "someFn" inside there is the function "checkStrings", because you passed it when you initialize flipperTester variable.
boolFlipper is, for our purposes here, a function decorator: it takes a function and modifies it to do something else. A more instructive example might be a logging function:
var alsoLogs = f => (...args) => {
var result = f(...args);
console.log(result);
return result;
};
// now we have a function that adds 2 numbers:
var add = function add(a, b) { return a + b; };
// and we want to also log the result
var addAndLog = alsoLogs(add); // addAndLog is a function, would be the whatTheHeckIsThis from your example
addAndLog(2, 3); // logs 5 to the console
If you don't understand all the ES6 syntax that's ok, just understand that alsoLogs take a function f and returns a function that does the exact same thing as f but also logs the result to the console.
Since we as programmers are lazy, we don't want to have to write functions to glue together other functions every time we want to do this, so we write a function to do it for us, compose.
So now we can just say something like:
var addAndLog = R.compose(console.log, add);
addAndLog(2, 3); // logs 5 to the console
I don't quite understand this bit of code.
$('div').click((function () {
var number = 0;
return function () {
alert(++number);
};
})());
My understanding is:
An anonymous function is defined and assigned to the click handler.
When I click on div, this function is invoked.
What the function does is:
Define a variable number = 0
Return ++number
So why does the number in alert increment every time I click? Shouldn't number be reset to 0 every time I click?
Here you've got a self-invoking function, which returns a function. Watch out for the brackets at the end:
(function () {
var number = 0;
return function () {
alert(++number);
};
})()
So the callback of the click handler is only the returned inner function:
function () {
alert(++number);
};
This inner function has access to the variable number, which is in the scope of the outer function.
So your code can also be written as follows:
function outerFunction() {
var number = 0;
return function () {
alert(++number);
};
};
var innerFunction = outerFunction();
$('div').click(innerFunction);
If we used (ugly) names for the anonymous functions, your code could be rewritten as:
$('div').click((function makeIncrementer() {
var number = 0;
return function incrementAndAlert() {
alert(++number);
};
})());
More verbose code retaining similar semantics would be:
var makeIncrementer = function() {
var number = 0;
return function() { alert(++number); };
};
var incrementAndAlert = makeIncrementer(); // function() { alert(++number); }
$('div').click(incrementAndAlert);
makeIncrementer is a function that, when called, defines a number variable in its scope, and returns a function - note that makeIncrementer doesn't increment, nor alert the number variable, instead it returns another function that does just that.
Now incrementAndAlert is bound to this returned function
function() { alert(++number); }
that captures makeIncrementer's number variable, which enables it to keep number's state between incrementAndAlert calls triggered by $('div') clicks.
This is not an "answer", but hopefully it will show a different way of looking at the problem.
First off, note that JavaScript functions are just objects and are thus just values that can be bound to variables. As such,
$('div').click((function () {
var number = 0;
return function () {
alert(++number);
};
})());
can be, with a simple expression substitution, rewritten as
var f = function () {
var number = 0;
return function () {
alert(++number);
};
};
// $('div').click((f)()); and when removing extra parenthesis ->
$('div').click(f());
Then, after one more simple expression substitution
var g = f()
$('div').click(g);
it should be clear that the (outer) function, f, is invoked first and it is the resulting (inner function) value, g, that is used as the handler.
Aside from introducing variables, the above substitutions are semantically equivalent to the original code.
Basically I want to do this:
someFunction() // do something
someFunction.somePropertyFunction()
someFunction() // Now someFunction is modified; it should now exhibit a different behaviour
Is this possible?
EDIT:
I'm not looking for what #Kolink was suggesting. Basically I want to augment a function's functionality by calling one of it's property function.
Specifically, I need to: 1. have access to the original function inside my property function (which is entirely doable using this), and 2. bind a new function to the original function's name (which I'm not sure if it's possible).
Just to be clear, I don't have access to the internal definition of the function that I want to augment. I want to attach a function to Function.prototype (so that it will be available as a property of the function that I want to augment), and then I will call func.augmentThis(), and then func should be augmented. But I'm not sure how, hence the question :P
Easily. Here's an example:
var derp = 123;
someFunction = function() {alert(derp);};
someFunction.somePropertyFunction = function() {derp = 456;};
someFunction(); // alerts 123
someFunction.somePropertyFunction();
someFunction(); // alerts 456
Okay, that's an oversimplified example, but yeah, it's entirely possible.
If your question is whether a function attached as a property to another function has a way to access the function to which it is attached, the answer is no. After all, the same function could be attached to any number of functions of objects.
So one alternative is to explicitly refer to the "mother" function within the function that is attached to it and intended to change its behavior:
function f (n) { alert (n + f.offset); }
f.offset = 0;
f.change_offset = function (i) { f.offset = i; };
f (1); //1
f.change_offset (100);
f (1); //101
Here, f is hard-wired into the definition of change_offset. If this bothers you, or you want something slightly more general, write a little routine to set a function as a property on another function, while binding its this to the function being attached to:
function set_func_as_func_prop ( propname, func_to_set, func_to_set_on ) {
func_to_set_on[propname] = func_to_set.bind(func_to_set_on);
}
Now you can write the function more generally
function change_offset (i) {
this.offset = i;
}
and set it on f or any other function.
set_func_as_func_prop ("change_offset", change_offset, f);
set_func_as_func_prop ("change_offset", change_offset, g);
Sort of:
function someFunction() {
return realFunction.apply(this, arguments);
}
function someFunctionA(name) {
return 'Hello, ' + name + '!';
}
function someFunctionB(name) {
return 'Goodbye, ' + name + '...';
}
var realFunction = someFunctionA;
someFunction.somePropertyFunction = function () {
realFunction = someFunctionB;
};
Sure it's possible. It's not recommended, but it's possible. For example:
function a() {
alert("a");
}
function b() {
alert("b");
}
function c() {
return c.f.apply(this, arguments);
}
c.f = a;
c.toggle = function () {
c.f = c.f === a ? b : a;
};
Now let's test it:
c(); // alerts "a"
c.toggle();
c(); // alerts "b"
See the demo: http://jsfiddle.net/LwKM3/
I want to attach a function to Function.prototype. Then I need to bind a new function to the original function's name (which I'm not sure if it's possible).
That indeed is impossible, you don't know what refers to the function. And you cannot change the internal representation of a function, which is immutable.
The only thing you can do is to create a new function and return that, to let the caller of your method use it somehow - specifically assigning it to the original variable:
somefunction = somefunction.augmentSomehow();
Your method for that will look like this:
Function.prototype.augmentSomehow = function() {
var origFn = this;
return function() {
// in here, do something special
// which might include invoking origFn() in a different way
};
};
Not sure if this helps, but I would implement described problem in following way:
// defined by somebody else - unknown to developer
var someFunction = function() {
alert("this is initial behavior");
}
someFunction(); // returns "this is initial behavior"
// defines parent object on which someFunction() is called
var parentObject = this; // returns window object (as called direclty in the
// browser)
// if you are calling someFunction from some object (object.someFunction())
// it would be:
// var parentObject = object;
// augumentThis definition
someFunction.augumentThis = function() {
var newFunction = function() {
alert("this is changed behavior");
};
parentObject.someFunction.somePropertyFunction = function() {
parentObject.someFunction = newFunction;
parentObject.someFunction();
};
};
someFunction.augumentThis(); // change function behavior
someFunction(); // "this is initial behavior"
someFunction.somePropertyFunction(); // "this is changed behavior"
someFunction(); // "this is changed behavior"
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 )