Javascript function inside functions - javascript

Today I observed the following syntax (simplified example):
const test = fn => () => console.log(fn)
test('foo')();
Having a hard time wrapping my head around this but it still remains vague to me. What exactly happens step by step?

Let's rewrite this in a way which maybe more understandable for you
const test = function(fn){
return function (){
console.log(fn);
}
}
test('foo')();
Do you understand it now? If yes this is same as your example just uses normal function instead of arrow functions.
You also need to know what a closure is to understand this.

As the answers already mentioned you are creating a closure.
In my answer, I want to say what it is a closure good for:
Imagin you want to greet three persons and two of them are your frinds and one is your boss. You want to greet your frinds with "Hi" but your boss with "Hello".
const greet = greetingWord => name =>
`${greetingWord}, ${name}`
const greetFrind = greet('Hi')
const greetBoss = greet('Hello')
We create a function greet which takes one arguement an will return a new function with one argument too (greet = greetingWord => name). Once we implement it we can define a greeter for our frinds and for the boss.
const greet = greetingWord => name =>
`${greetingWord}, ${name}`
const greetFrind = greet('Hi')
const greetBoss = greet('Hello')
console.log(greetFrind('Paul'))
console.log(greetFrind('Julia'))
console.log(greetBoss('Mr. Paker'))

So this is basic concept of closure in JavaScript. If you rewrite the code in ES5:
var test = function(fn){
return function(){
console.log(fn);
};
}
test('foo')();
So the inner function has access to the argument that was passed into the outer function. So that's why you are getting "foo"

Related

is const variable in javascript function initialized every time when it called or just once?

I'd like to code something like this.
function cokeDispencer(id) {
const dict = {1:"sprite", 2:"pepcy", ...} // Some JSON. It might be bigger.
return dict[id];
}
Of course, dict[id] is much simpler way to do the same, but I want put the dict object inside of function so that no other function can access to this dict object.
What I'm wondering is that the object dict is initialized everytime it called. As I know, function written in C/C++ initalize it's local variable everytime it called except static variable. If then, is there a way to initalize const variable just once like static variable C/C++?
Yes, you're creating a new dict object every time that function runs.
You can make an IIFE instead - a function that runs immediately and "closes" over the object and can return a function that accesses the desired property.
const cokeDispencer = (() => {
const dict = {1:"sprite", 2:"pepcy"} // Some JSON. It might be bigger.
return id => dict[id];
})();
console.log(cokeDispencer(1));
This is almost the same thing as
const dict = {1:"sprite", 2:"pepcy"} // Some JSON. It might be bigger.
const cokeDispencer = id => dict[id];
console.log(cokeDispencer(1));
except that the IIFE makes sure that only the cokeDispener function has access to the object.
If you want to create the object only the first time the function is called, and not before, you could use a pretty similar technique to assign to a variable scoped only to the function if needed.
const cokeDispencer = (() => {
let dict;
return (id) => {
if (!dict) {
dict = {1:"sprite", 2:"pepcy"} // Some JSON. It might be bigger.
}
return dict[id];
};
})();
console.log(cokeDispencer(1));

How to run an entire method with one word?

player.outputChatBox("Test")
Is there anyway I can run the method above with just one word?
For example, var test = player.outputChatBox("Teste")
If I type test wherever on the script it runs it.
Also, consider I'll add multiple of those, so the best option might be an object or something (sorry, I'm new).
Make a function that calls it.
const test = () => player.outputChatBox("Test");
test();
test();
test();
Add parameters if you want.
const test = (string = "Test") => player.outputChatBox(string);
test(); // output: 'Test'
test('foo'); // output: 'foo'
test(); // output: 'Test'
You could declare a helper function:
const helper = () => player.outputChatBox("Test")
This way you could use it sort-of the way you want:
helper();
helper();
helper();
Would call the function 3 times

Make an IIFE return variables for only some other IIFES

I was wondering if we can declare a variable in one IIFE and the return it but make it available for another specific IIFE? Here is an example!
So I have
const iife1 = (()=>{
const x = 10;
return x
})()
const iife2 = (()=>{/* MAKE X AVAILABLE ONLY IN THIS FUNCTION */})()
const iife3 = (()=>{/* HERE X CANNOT BE CALLED */})()
Maybe you would say just not to pass the variable x in the iif3 as an argument, but I was wondering if there is a conditional way we can achieve it when returning the variable from iif1, so the iif1 will know for which functions it returns its properties or methods before actually has returned!
My goal is to create an IIFE which in it I will declare all the variables that I am going to use in my project. Then for each variable, I want to have a proper condition so that when the IIFE with the variables returns the function has already decided in which scope will sent the variables for use! I don't know if this approach makes sense but as is always being said I am trying not to populate the global scope.
Codepen
One of the (probaby dozen) ways to achieve that is by using a Proxy.
First IIFE would create a proxy object through which you'd access its properties. After calling the revoke(), you will no longer be able to access any of the proxy's props.
As people have stated in their comments, there are probably much easier ways for you to achieve the wanted result, but you haven't presented the actual problem clearly.
const { proxy, revoke } = (() => {
const x = { test: 'test' };
const revocable = Proxy.revocable(x, {
get: (target, name) => name
});
return revocable;
})();
const test1 = (proxy => {
console.log('TEST 1', proxy.test);
})(proxy);
revoke();
const test2 = (proxy => {
console.log('TEST 2', proxy.test); // can't access
})(proxy);
Fiddle:
https://jsfiddle.net/ay92L1r6/6/
IIFEs can only use Global, Passed, or internal variables. You can't make something available to a function scope that isn't available to a second function in the same scope.
Passing variables is one way, but perhaps the more practical way in certain circumstances would be to just nest your IIFEs as needed
const iife2 = (() => {
const iife1 = (() => {
const x = 10;
return x
})()
console.log(iife1);
/*iife2 scope*/
})()
const iife3 = (() => { /* HERE X CANNOT BE CALLED */ })()
It is not necessary to use three IIFE, remember that as soon as your iife1 returns that value will be in the same scope of iife2 and iife3 thus you won't achieve your goal.
Your best bet is to declare iife2 and iife3 as normal functions and call them inside iife1 when some conditions are met and pass the variable that will create the scope of iife3 as argument.
this solution is more flexible and predictable than relying on the outer scope
const fn2 = function(x) {/* MAKE X AVAILABLE ONLY IN THIS FUNCTION */};
const fn3 = function() {/* HERE X CANNOT BE CALLED */};
(()=>{
const x = 10;
//your logic
fn2(x);
fn3();
})()

JavaScript Nested Functions cross referencing

I have a nested function that needs a return type of the previously declared function to use it as a function argument . I don't know if my structure is correct or can support this .
would be grateful for some advice on how to call it
var myObject = {
funct1 : (function (){..... return funct1; })(),
funct2 : (function (funct1){..... return func2; })(funct1)
};
So the question is how would I call that funct1 argument correctly in the second function
Do I use the myObject.Funct1 or is there another method of calling that object internally ...
Im currently getting a error
Cannot read property 'funct1' of undefined
I don't think there is a way to do this by declaring an object literal since the keys of the object can't be used during the object creation.
You can get the same functionality by doing this, though:
const myObject = (() => {
const func1 = () => 'result of func1';
const func2 = () => func1() + ' and func2';
return { func1, func2 }
})();
console.log(myObject.func2()); // result of func1 and func2

Curried JavaScript - calling

I am admittedly a beginner with JavaScript, but I need to piece together someone else's code and I am having trouble understanding the following function and how to call it in node.
const invoke = method => object => object[method]
This obviously is a function that takes a method that returns another function that takes an object that then returns object[method], but what exactly is the purpose? How would one use this? Thank you.
the way i see it is as the const states, it invokes a function stored in an object ,
as you mentionned, this can be broken down to :
const invoke = (method) => {
return (object) => {
return object[method] ;
}
}
the goal of this i believe is that you can call it ( like you're telling a story ) expressively and concisely : invoke the function a from the functions object. ( functionnal-programming )
from this article about functional programming
Functional programming is declarative rather than imperative, and
application state flows through pure functions. Contrast with object
oriented programming, where application state is usually shared and
colocated with methods in objects.
but the term invoke got me thinking about Immediately invoked functions, so the usage of the const invoke can be :
getting function from the object ( without executing it ) not to have to instantiate the whole object and having the function in a variable and maybe manipulate it's prototype.
calling the function ( with parenthesis ).
getting a property from an object.
immediately invoke a function in an object.
const myFns = {
'a' : function(x){
console.log(x || 'something to log when no params passed');
},
'b': {
username : 'Doe'
}
}
const invoke = method => object => object[method]
let myFunction = invoke('a')(myFns);
myFunction('hello from myFunction'); // call it or modify myFunction.prototype ... etc.
invoke('a')(myFns)('hello'); // simply call it
let user = invoke('b')(myFns); // get a property
console.log(user.username);
(invoke('a')(myFns))(); // immidiatly invoke the function
probalby to avoid eval() :P
The name 'invoke' suggests it should really be written like this:
const invoke = method => object => object[method]()
The () is the invocation. It's very general, so hard to say exactly how it would be used, but here's a silly example.
class Dog {
speak () { console.log('woof') }
}
var dogs = [ new Dog(), new Dog(), new Dog() ];
dogs.forEach( invoke( 'speak' ) );
-> 'woof'
-> 'woof'
-> 'woof'
It's a pretty common pattern to let an array method like forEach do the second call of a higher-order function like this.

Categories