I am new to Javascript and learning about closures and nested scope.
The prompt asks for this:
Write a function that has three nested functions, each taking one number as an argument. The inner-most function should return the sum of all three numbers.
This is what I have come up:
var outMost = function (num1) {
var x = num1;
var innerMost = function (num2) {
var y = num2;
var innerInnerMost = function (num3) {
console.log(x + y + num3);
}
return innerInnerMost;
}
return innerMost;
}
var firstNum = outMost(1);
firstNum(2);
firstNum((3));
Please help me understand what I am doing wrong -- I have gone on numerous website to learn about closures and scope but nothing seems to explain it well. Thank you for the help.
When you call firstNum(2), you are not catching the return-value (which is a function). If I run your code in Node.js REPL, here is what it looks like:
> var firstNum = outMost(1);
undefined
> firstNum(2);
[Function]
> firstNum((3));
[Function]
Try this in the end instead:
var firstNum = outMost(1);
var secondNum = firstNum(2);
secondNum(3);
Here is what it looks like in Node.js REPL:
> var firstNum = outMost(1);
undefined
> var secondNum = firstNum(2);
undefined
> secondNum(3);
6
undefined
Please note that assignment evaluates to undefined. Also, since innerInnerMost doesn't return anything, there is an implicit return undefined in the end.
function firstFunc(x){
return function secondFunc(y){
return function thirdFunc(z){
console.log(x+y+z);
}
}
}
Calling:
var ff = firstFunc(1);
var sf = ff(2);
sf(3);
very easy look at this example
if you have this type
in ES6
let f = () => {
return () => {
console.log('First function called');
return () => {
console.log('Second function called');
}
}
}
you have two way to call every function, first of all, I want to call the First function
in this way f()() and then I want to call the Second function f()()().
First of all, you will be seeing in console
First function called
and then
Second function called
and another way you can use this technic
let f1 = f();
let f2 = f1();
you will be seeing
First function called
if you want to the second function call
let f1 = f();
let f2 = f1();
let f3 = f2();
and then you will be seeing
Second function called
if you want to change this code to ES5
var f = function() {
return function() {
console.log('First function');
return function(){
console.log('Second function');
}
}
}
two way of call
var f1 = f();
var f2 = f1();
var f3 = f2();
f()()();
Related
ok so, it's 3am here and this stupid issue is keeping me up, bothering me all night long,
basically what i was trying to do is to make a function that takes an existing function as a parameter to return a constructor function, maybe this will be obvious reading my code
var f = function() {
return function(p) {
return document.createElement(p)
}
};
var x = f();
alert(x); //alerts function(p){ return document.createElement(p)}
var n = x("div"); //it creates div Element
alert(n); // alert [object HTMLDivElement]
the code above works just fine but i want to use variables instead of putting the createElement directly inside the constructor function, i want to pass it as a parameter to the function f like this
var f = function(dd) {
return function(p) {
return dd(p)
}
};
var x = f(document.createElement);
alert(x); //alerts function(p){ return dd(p)}
var n = x("div"); //doesn't createElement
alert(n); //doesn't alert
in addition to that , the last code outputs something weird in the console illegal invocation, I have no idea whats wrong wmy code, please help?
You have to bind the createElement method to the document object. Otherwise, you're calling a method, but it doesn't have the proper context.
var f = function(dd) {
return function(p) {
return dd(p)
}
};
var x = f(document.createElement.bind(document));
alert(x);
var n = x("div");
alert(n);
The arrow function version would be
var f = dd => p => dd(p);
var x = f(document.createElement.bind(document));
alert(x);
var n = x("div");
alert(n);
You have to bind the createElement method to the document
var x = f(document.createElement.bind(document));
See this example:
var tools1 = require('../tools/tools1');
var test_func = function(arg1, arg2, arg3) {
var local_var_1 = "lc1";
var local_var_2 = "lc2";
return function(data) {
var result = tools1.doSth(local_var_1);
result = result+local_var_2;
}
}
exports.test_func = test_func;
I do not understand what does inner function do what it is for!
In javascript when you return function it returns reference of that function and you can call it later.
In your Code when you do var result = test_func(), result will hold reference of that function. Then later you can call that returned function like result(data).
A basic example:
function sum(x, y) {
var rs = x+y;
return function(message) {
console.log(message + rs); //rs holds its value because of clousers
}
}
var result = sum(2, 3);
result("This is result: ");
Variables that are used locally, but defined in an enclosing scope
like rs in above example because of Closures
This concept of function inside a function is known as closure in JavaScript. They are self invoking and makes it possible to have a function's private variables.
I am representing a similiar code of yours which I found in W3schools.com.
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
add();
add();
add();
Initially, the counter is set to 0 and then it returns a function reference. The counter is protected by the scope of the anonymous function, and can only be changed using the add() function.
The counter is set to 3 then, as add() function is called three times.
In the very similiar way, your code is working I guess:
var test_func = function(arg1, arg2, arg3) {
var local_var_1 = "lc1";
var local_var_2 = "lc2";
return function(data) {
var result = tools1.doSth(local_var_1);
result = result+local_var_2;
}
}
the local_var_1 and local_var_2 is set to "lc1' and "lc2" and returning a function reference.
The inner function then comes and do some operation with tools1.doSth() on local_var_1 and append the result with local_var_2.
Note: I am not clear with the output of your code, so I tried to tell you the steps with help of another code.
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 came across this syntax in "Hey Underscore, You're Doing it Wrong" JavaScript talk (4:15). I would like to know what it means.
var add = function(x,y){
return x + y;
}.autoCurry();//What is happening in this line.
First let's looks at what curry and autocurry actually do. I've annotated the source of these two functions (originally found in the wu.js library):
////
// Type:
//
// ((a,b, ... c) -> d) -> a -> b -> ... -> c -> d
//
// Example:
//
// function add(a, b) { return a + b; }
// add2 = curry(add, 2)
// add2(3)
// // 5
function curry(fn /* variadic number of args */) {
var args = Array.prototype.slice.call(arguments, 1);
function f() { return fn.apply(this, args.concat(toArray(arguments))); }
return f;
}
////
// Example:
//
// function add(a, b) { return a + b; }
// autoCurry(add);
//
// add(2)(3)
// // 5
//
// add(2, 3)
// // 5
function autoCurry(fn, numArgs) {
numArgs = numArgs || fn.length;
function f() {
if (arguments.length < numArgs)
{
return numArgs - arguments.length > 0 ?
autoCurry(curry.apply(this, [fn].concat(toArray(arguments))),
numArgs - arguments.length) :
curry.apply(this, [fn].concat(toArray(arguments)));
}
else
{
return fn.apply(this, arguments);
}
}
f.toString = function() { return fn.toString(); };
f.curried = true;
return f;
}
In other words,
autoCurry(add)
Takes a function that takes two arguments and returns a number, and returns a function A that takes a single argument and returns a function B. Where B is a function that takes a single argument and returns a number:
add(1) -> returns a function add1(), which itself takes a single argument.
Next, the speaker in that talk does the following:
Function.prototype.autoCurry = function(n) { return autoCurry(this, n); }
This simply applies the autoCurry method to any given function (self) so that
var add = function(x,y){
return x + y;
}.autoCurry();
Has the same effect as:
var add = function(x,y) { return x + y; };
add = autoCurry(add)
Well, I can't tell you what, exactly autoCurry is doing... ...but what I can tell you is this:
They've modified the Function constructor's prototype Function.prototype.autoCurry = function () { };
Every new function you make on that page will now have access to this method as one of its properties.
var myFunc = function () { return true; }; myFunc.autoCurry();
You can chain statements together, happily in JS.
var myObj = { run : function () { } }, result = myObj.run(); is the same as
var result = { run : function () { } }.run();, as long as you don't care about myObj after.
So:
You are creating a function, and as soon as it's created, you're running a method on it, and the return statement of that method (the last thing in the chain) is being saved to the variable.
Now, currying is a form of taking a function and wrapping it in other functions, which allows you to call it with only a portion of the arguments needed.
function add_two_numbers = function (x, y) { return x + y; }
Currying would allow you to do this:
var save_x_for_later = curry(add_two_numbers),
save_y_and_add = save_x_for_later(3),
result = save_y_and_add(5);
result; // 8
As for your new title, the answer is the following:
You will get an error thrown in your face:
.autoCurry() is not a part of the language.
It was written, by hand, and put on the Function.prototype as Function.prototype.autoCurry = function () { }
I could go into an implementation of currying, but there's a lot of stuff to wrap your head around, if you haven't done much functional programming, or if "lambda" is a head-scratching term.
In JavaScript, a function instantiation expression:
function name( arg1, arg2, ... ) { /* code */ }
creates a function and results in a reference to the function object. Thus, the .autoCurry() is a reference to a property on that object, which is apparently assumed to be a function.
I suspect that the example you're looking at has some other code that adds "autoCurry" to the Function prototype object. That way, every function object has access to that function as the "autoCurry" property.
Can you explain me why does the second call of fn gives an error? The code is below.
function Test(n) {
this.test = n;
var bob = function (n) {
this.test = n;
};
this.fn = function (n) {
bob(n);
console.log(this.test);
};
}
var test = new Test(5);
test.fn(1); // returns 5
test.fn(2); // returns TypeError: 'undefined' is not a function
Here's a JSfiddle that reproduces the error http://jsfiddle.net/KjkQ2/
Your bob function is called from the global scope. Thefore, this.test is pointing at a global variable named test which is overwriting the variable you created. If you run console.log(window.test), you'll what's happening.
For your code to behave as intended, you would need one of the following
function Test(n) {
this.test = n;
// If a function needs 'this' it should be attached to 'this'
this.bob = function (n) {
this.test = n;
};
this.fn = function (n) {
// and called with this.functionName
this.bob(n);
console.log(this.test);
};
}
OR
function Test(n) {
this.test = n;
var bob = function (n) {
this.test = n;
};
this.fn = function (n) {
// Make sure you call bob with the right 'this'
bob.call(this, n);
console.log(this.test);
};
}
OR closure based objects
// Just use closures instead of relying on this
function Test(n) {
var test = n;
var bob = function (n) {
test = n;
};
this.fn = function (n) {
bob(n);
console.log(test);
};
}
When calling bob(n) within .fn, it is called within the global context (window in a browser). Now, you're setting window.test = n; which basically overwrites your function test object you created earlier.
If we you write this more explicit, it becomes more obvious:
// in the global scope, `test` gets written to the `global object`
// window.test = new Test(5);
var test = new Test(5);
test.fn(1); // returns 5
test.fn(2); // returns TypeError: 'undefined' is not a function
You can "workaround" this issue by calling bob() with an explicit context, using .call() for instance:
this.fn = function (n) {
bob.call(this,n);
console.log(this.test);
};
The root of evil here is, that the value of this is dynamically assigned during run-time. Don't get me wrong, its actually a great feature of ECMAscript - it's just the problem for you here. When you call a function, "just like that", this will always reference the global object.
You want to call bob.call(this, n), not just bob(n).
When you call bob(n), the value of this is not your object, it's window. Therefore, your test variable is replaced with 1.
In jsFiddle, the code is wrapped in a function, so window.test does not exist at first.