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
Related
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 have the code below:
//anonymous function expression
var a = function() {
return 3;
}
//named function expression
var a = function bar() {
return 3;
}
So, what is the different between them ? (technical, usage)
The main differences are
You can inspect the function name (for example stack traces are more readable)
The function can be recursive
Note that a function like
var fibo = function(n) {
return n<2 ? 1 : fibo(n-1) + fibo(n-2);
};
is not really recursive as its body will call whatever fibo is bound to at the moment of the call (so it will not call itself if fibo is later assigned to something else). The version
var f = function fibo(n) {
return n<2 ? 1 : fibo(n-1) + fibo(n-2);
};
is instead really recursive and will keep calling itself no matter what f is later bound to.
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
I'm trying to make a function that can be applied to a value returned from another function both within a function. Since that's probably a terrible explanation, here's a simplified sample:
function MainFnc() {
this.subFnc=function(a) {
return a*2
}
this.subFnc.subSubFnc=function(a) {
return this*a
}
}
This isn't my actual code - it's for a far better reason than multiplying numbers. This is just a simplified example of what I'm trying to achieve. My question is whether or not it's actually possible to go this deep, and if so how? The method I've portrayed in this sample code evidently does not work.
Thanks for any help.
Edit: Here's an example of it in use since not everyone understands clearly what I want to do with this:
anObject=new MainFnc;
alert(anObject.subFnc(2)); //returns 4
alert(anObject.subFnc(2).subSubFnc(2); //returns 8
This is not exactly what I'm doing, it's just easier to understand using simple multiplication.
This is about as close as you can get:
function foo(n){
this.value = n;
return this;
};
foo.prototype = {
valueOf : function(){
return this.value;
},
multiplyBy : function(n){
return new foo(this.value * n);
}
};
foo.prototype.toString = foo.prototype.valueOf;
var x = new foo(2);
var y = x.multiplyBy(2).multiplyBy(2).multiplyBy(2);
// y == 16
Update based on your comment:
MainFnc is an object which is created in a variable (ie MainVar). So if I wanted to try MainVar.subFnc(2) it'd return 4. If I wanted to try MainVar.subFnc(2).subSubFnc(2), however, it'd return 8.
Right now, you're returning a number from your subFnc, and so the expression MainVar.subFnc(2).subSubFnc(2) breaks down like this:
Look up the property subFnc on MainVar; it returns a function reference.
Call the function with this = MainVar; this returns the number 2.
Look up the property subSubFnc on the number 2; it returns undefined.
Call the function with this = 2; fails because you can't call undefined as a function.
More: You must remember this and Mythical Methods
To do what you're doing, you'd have to have subFnc return an object with function properties. You could do it like this:
function MainFnc(val) {
this.value = val;
this.mult=function(a) {
return new MainFnc(this.value * a);
};
this.div=function(a) {
return new MainFnc(this.value / a);
};
this.get = function() {
return this.value;
};
}
...and then call it like this:
var MainVar = new MainFnc(3);
alert(MainVar.mult(3).mult(4).div(6).get()); // alerts "6" (3 * 3 * 4 / 6 = 6)
Live example
Note the get function to return the underlying number. You might also add a toString:
this.toString = function() {
return String(this.value);
};
But the above isn't taking advantage of prototypical inheritance at all (and it will be important to, if you're creating all of those objects; we need to keep them lightweight); you might consider:
function MainFnc(val) {
this.value = val;
}
MainFnc.prototype.mult = function(a) {
return new MainFnc(this.value * a);
};
MainFnc.prototype.div = function(a) {
return new MainFnc(this.value / a);
};
MainFnc.prototype.get = function() {
return this.value;
};
MainFnc.prototype.toString = function() {
return String(this.value);
};
Original Answer:
With that code, if you did this:
var f = new MainFnc();
alert(f.subFnc(3)); // alerts "6"
alert(f.subFnc.subSubFnc(3)); // NaN
...because this inside subSubFnc when called like that is subFnc, and multipling a function reference tries to convert it to a number, which comes out NaN, and so the result of the multiplication is NaN.
Remember that in JavaScript, this is defined entirely by how a function is called, not where the function is defined. When you call a function via dotted notation (a.b();), the object you're looking up the property on becomes this within the function call, and so with a.b.c();, this within c() is b, not a. More: You must remember this and Mythical Methods