Callback function syntax in Javascirpt - javascript

Guys i am a newbie in Javascript and i really need your help.
const f = ()=>{
}
const y = f(()=>{
})
What does this code do ? Why we write y function this way instead of doing like this.
const y = f()=>{
}

const y = f(()=>{}) passes an arrow function as the first argument to the function f and stores the return value of f in the variable y. Passing functions to other functions is commonly used for callbacks.
const f = arg => {
console.log('first argument to f', arg);
return "return value";
}
const y = f(()=>{});
console.log(y);

The following code is invalid. So you cannot write a function like that
const y = f()=>{
}
The reason the code const y = f(()=>{}) is written like that is because f is a function, hence the f(). You're calling f with the first argument being an anonymous function. f will do something with that function, as with any other function argument.
That's called passing a "callback" as an argument. You can read more here
The example from MDN:
function greeting(name) {
alert(`Hello, ${name}`);
}
// this would be your `f` function
function processUserInput(callback) {
const name = prompt("Please enter your name.");
callback(name);
}
processUserInput(greeting);
The code const f = ()=>{} is a normal function called f.

Related

Weird behavior when using curly brackets in arrow function expressions with Fetch API [duplicate]

I'm new to both ES6 and React and I keep seeing arrow functions. Why is it that some arrow functions use curly braces after the fat arrow and some use parentheses?
For example:
const foo = (params) => (
<span>
<p>Content</p>
</span>
);
vs.
const handleBar = (e) => {
e.preventDefault();
dispatch('logout');
};
The parenthesis are returning a single value, the curly braces are executing multiple lines of code.
Your example looks confusing because it's using JSX which looks like multiple "lines" but really just gets compiled to a single "element."
Here are some more examples that all do the same thing:
const a = (who) => "hello " + who + "!";
const b = (who) => ("hello " + who + "!");
const c = (who) => (
"hello " + who + "!"
);
const d = (who) => (
"hello "
+ who
+ "!"
);
const e = (who) => {
return "hello " + who + "!";
};
You will also often see parenthesis around object literals because that's a way to avoid the parser treating it as a code block:
const x = () => {} // Does nothing
const y = () => ({}) // returns an object
One can also use curly braces to prevent a single line arrow function from returning a value -- or to make it obvious to the next developer that a single line arrow function shouldn't, in this case, be returning anything.
For example:
const myFunc = (stuff) => { someArray.push(stuff) }
const otherFunc = (stuff) => someArray.push(stuff)
console.log(myFunc()) // --> logs undefined
console.log(otherFunc()) // --> logs result of push which is new array length
Parenthesis are used in an arrow function to return an object.
() => ({ name: 'YourName' }) // This will return an object
That is equivalent to
() => {
return { name : 'YourName' }
}
Actually in a briefcase when somebody uses braces in an arrow function declaration, it is equal to below:
const arrow = number => number + 1;
|||
const arrow = (number) => number + 1;
|||
const arrow = (number) => ( number + 1 );
|||
const arrow = (number) => { return number + 1 };
Parenthesis has an implicit return statement while curly braces you need an explicit return statement
If you use curly braces after the arrow to define the function body, you have to use the 'return' keyword to return something.
For example:
const myFun1 = (x) => {
return x;
}; // It will return x
const myFun2 = (x) => {
x;
}; // It will return nothing
If you use the parenthesis, you don't need to mention the 'return' keyword.
For example:
const myFunc1 = (x) => x; // It will return x
const myFunc2 = (x) => (x); // It will also return x
In your first example, the right-hand side of the arrow function shows a single expression that is enclosed by a grouping operator:
const foo = (params) => (
<span>
<p>Content</p>
</span>
);
A similar comparable case would be the following:
const foo = (params) => (<span><p>Content</p></span>);
A distinction, in the above cases using single expressions, is that the right-hand side is the returned value of the function.
On the other hand, if you use curly braces, JavaScript will understand that as a statement:
const foo = (params) => {} // this is not an object being returned, it's just an empty statement
Therefore, using statement is a good start for you to have code in it, multiple lines, and it will require the use of "return" if the function is intended to return value:
const foo = (params) => {
let value = 1;
return value;
}
In case you wanted to return an empty object in the shortest form:
const foo = (params) => ({})
See tests
To answer a duplicate post(question posted here), just for reference for others:
var func = x => x * x;
// concise body syntax, implied "return"
var func = (x, y) => { return x + y; };
// with block body, explicit "return" needed
For reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Function_body
Also note:
If you are returning an object literal as the result from a fat arrow function, then you must enclose the object in parentheses, e.g., myFunc = () => ({ data: "hello"}). You will receive an error if you omit the parentheses because the build tools will assume that the curly braces of the object literal are the start and end of a function body.
Every function has 2 aspects.
First of them is that each one, not just the arrow functions, has an execution context (a block scope) in which the variables are created and used.
In other words, inside the curly braces { ... } of the function, what is declared and assigned there, stays there and is not visible to the outside functions / or variables.
For example, when writing something as
let x = 100;
function doSomething() {
let x = 50;
console.log(x);
}
doSomething(); // 50
console.log(x); // 100
both values are displayed in console (instead of 'x from outside just being replaced by x from inside the function').
You see that despite of let not usually allowing other variable x to be declared again (with the same name x), in this case, because the second x is declared and initialized inside the { ... }, it does not alter the outside one, which also happens because after the function doSomething is called, the x from inside of it is created, assigned, printed in console and then destroyed (deleted from the memory). So that process happens every time we call that function by running doSomething() .
So this is the first aspect to take into consideration when understanding the functions: they execute then forget the values created by the code inside their curly braces.
Because of it, it's easier to understand their second aspect -- as functions cannot just work isolated from the others, they need to also send data to the others, so they have some 'reporting aspect' used to externalize some part of the results computed inside their curly braces, which is exactly why the return statement exists.
Return exists in each function, even in the console.log or alert(), even in doSomething(), but in these cases where we didn't explicitly set something for it, it is always 'return undefined'.
Therefore it isn't necessary to write it, but instead know that where you don't return something specific, the function itself will do it for you by returning undefined.
When you write (or use) a function meant just to execute something, it will also return undefined. Always.
You can check that thing with every function which (apparently) has no declared return:
let x = alert(100);
console.log(x); // undefined
let y = doSomething(); // console prints 50
console.log(y); // 50, then undefined --- 2 lines
console.log(alert('Hello')); // undefined
console.log(console.log('Okay')); // Okay , then undefined
Why is that?
Because alert() which is a method of global object window (in browser) (so it is actually window.alert() ) and also console.log() (which is the same with window.console.log() , too), execute something (printing in an alert box or in the console whatever is in between the () AND THEN return undefined).
Now, coming back to the arrow functions, they are not just some new way of notation for writing the functions but they also have some specific features.
First, if you only have a parameter between the () in an arrow function, you can write it without the parentheses.
Second, if inside the curly braces there's a single statement, you can omit as well the curly braces.
Third one, if the single statement is a return statement, you can omit the word return.
Somehow, using these we could transform many usual functions into arrow functions if needed:
function doSomething() {let x = 50; console.log(x);} // as function declaration
let doSomething = function() {let x = 50; console.log(x);}; // as function expression, which is an anonymous function assigned to the variable 'doSomething'
let doSomething = () => {let x = 50; console.log(x);}; // as arrow function
// let's transform it further
let doSomething = () => {console.log(50)}; //
// that is equivalent to ---- let doSomething = () => {console.log(50); return undefined};
// or even to ---- let doSomething = () => {return ( console.log(50) ) };
// because anyways, *console.log* has *return undefined* in it, as explained above
//which is the same as ---- let doSomething = () => {return console.log(50) };
// let's now apply the rules 2 and 3 from above, one by one:
let doSomething = () => return console.log(50);
let doSomething = () => console.log(50);
// Obviously, this just shows how we could rewrite many usual functions (functions declarations) into arrow functions
// we can do that safely if we don't have any **this** involved in the functions, of course
// also, from all lines of code above only one must remain, for example the last one.
// the last one, despite only having ---- console.log(50) --- as the execution aspect, it also ---- returns undefined ---- as well
// obviously ---- console.log( typeof doSomething ); // function
// while ---- console.log( typeof doSomething() ); // undefined
If an arrow function has 2 or more parameters, we cannot omit the parentheses around them:
function sum(a, b) {let total = a + b; return total}
let sum = function(a, b) {let total = a + b; return total};
// or
let sum = (a, b) => {let total = a + b; return total};
// or
let sum = (a, b) => {return a + b};
// or
let sum = (a, b) => a + b;
For simple operations as above, the fat arrow sign '=>' can be "read" as is transformed into, in other words, a and b is (are) transformed into a + b.
Opposite to that, there are also functions that validate some data (for example checking the data type, etc), like this one
let isNumber = x => typeof x === "number";
// or
let isNumber = (x) => {return (typeof x === "number")};
// obviously,
isNumber("Hello, John!"); // false
Those DON'T transform the data, and thus the arrow sign can be read something more as with the condition that, or similar.
In other words, a function like
let double = x => x * 2 // 'double' is a function that transforms x into x*2
is not the same as a checking one (mostly used in filters, sort, and other kind of validating functions, usually as callback function, etc)
let isArray = arr => Array.isArray(arr) // that last one already returns boolean by itself, no need to write return (Array.isArray() etc)
Last thing to know about return is that when you write code in multiple lines, the ASI (Automatic Semicolon Insertion) will insert a ';' after return if you mistakenly press enter after writing the return word, which will break the code, therefore instead of
return
a+b;
your code will behave as
return;
a+b;
so you better write the code with parentheses as here:
return (
a + b
);
as explained in MDN website here, too.

about javascript arrow function expression

I am Korean, so I hope you could understand it with my awkward English skills
I am studying arrow function expressions
and here is my question with source code
var arguments = [1, 2, 3];
var arr = () => arguments[0];
console.log(
arr()
)
function foo(n){
var f = () => arguments[0] + n
console.log(arguments[0]) //5
console.log("----arguments[0]")
return f();
}
console.log(
foo(5)
)
console.log("---------------------")
function fooo(n){
var f = (...arguments) => arguments[0] + n
console.log(...arguments) //5
console.log("----...arguments")
return f(2);
}
console.log(
fooo(5)
)
I don't get why the second function's console.log = 10 and third function's = 7
can anyone explain to me the order code process and why that output is?
thank you.
In JS, every conventional function has a built-in object called arguments. However, Arrow functions do not have this built-in object. So, if referred to arguments from within an Arrow function, the reference automatically goes to any external variable declared by that name.
The result you see is due to this effect. In regular function calls. your reference to the arguments global variable actually refers to their in-built arguments object.
The following code demonstrates this effect.
let arguments = 'this is a string';
function argumentsTest() {
console.log(arguments);
}
let argumentsArrowTest = () => {
console.log(arguments);
}
argumentsTest(10); //{0: 10}
argumentsArrowTest(10); // this is a string
In an arrow function, arguments, like this, will refer to either
an outer identifier named arguments (though it's very unusual to call a variable arguments due to name collision), or
the arguments provided to a full-fledged function
whichever is closer, lexically.
In foo,
var f = () => arguments[0] + n
is an arrow function, so arguments refers to an outer binding. The outer environment is
function foo(n){
var f = () => arguments[0] + n
so arguments refers to the arguments provided to foo. Here, it's similar to doing
function foo(n){
const theArguments = [n];
var f = () => theArguments[0] + n
And since the argument passed to foo is 5, that plus n (the same argument) is 10.
In the third function, the same logic applies. Inside an arrow function, arguments refers to the closest identifier named arguments, or the closest function. Here, it's the parameters:
var f = (...arguments) => arguments[0] + n
Since f is called with a single argument, this simplifies to
var f = (arg) => arg + n
That argument is 2, and the n is what's passed to fooo, which is 5. Add them together, you get 7.

function declare as a arrow function, later want to rebind with other object? [duplicate]

I've been experimenting with ES6 for a while now, and I've just come to a slight problem.
I really like using arrow functions, and whenever I can, I use them.
However, it would appear that you can't bind them!
Here is the function:
var f = () => console.log(this);
Here is the object I want to bind the function to:
var o = {'a': 42};
And here is how I would bind f to o:
var fBound = f.bind(o);
And then I can just call fBound:
fBound();
Which will output this (the o object):
{'a': 42}
Cool! Lovely! Except that it doesn't work. Instead of outputting the o object, it outputs the window object.
So I'd like to know: can you bind arrow functions? (And if so, how?)
I've tested the code above in Google Chrome 48 and Firefox 43, and the result is the same.
You cannot rebind this in an arrow function. It will always be defined as the context in which it was defined. If you require this to be meaningful you should use a normal function.
From the ECMAScript 2015 Spec:
Any reference to arguments, super, this, or new.target within an ArrowFunction must resolve to a binding in a lexically enclosing environment. Typically this will be the Function Environment of an immediately enclosing function.
To be complete, you can re-bind arrow functions, you just can't change the meaning of this.
bind still has value for function arguments:
((a, b, c) => {
console.info(a, b, c) // 1, 2, 3
}).bind(undefined, 1, 2, 3)()
Try it here:
http://jsbin.com/motihanopi/edit?js,console
From the MDN:
An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value (does not bind its own this, arguments, super, or new.target). Arrow functions are always anonymous.
This means you cannot bind a value to this like you want.
description: Stijn de Witt
You cannot use bind to change the value of this inside an arrow function. However, you can create a new regular function that does the same thing as the old arrow function and then use call or bind to re-bind this as usual.
We use an eval call here to recreate the arrow function you pass in as a normal function and then use call to invoke it with a different this:
code: me
const func = v => console.log(this);
const obj = {value: 10};
function arrowBindOld(context, fn) {
let arrowFn;
(function() {
arrowFn = eval(fn.toString());
arrowFn();
}).call(context);
}
arrowBindOld(obj, func);
update
const f = v => console.log(this, v);
const o = {value: 10};
/* new */
function arrowBind(context, fn) {
const arrowFnString = fn.toString();
return (function() {
return eval(arrowFnString);
}).call(context);
}
const fBound = arrowBind(o, f);
fBound(10);
/* use prototype */
Function.prototype.arrowBind = function(context) {
const arrowFnString = this.toString();
return (function() {
return eval(arrowFnString);
}).call(context);
}
const fBoundProto = f.arrowBind(o);
fBoundProto(20);
For years, js developers struggled with context binding, asked why this changed in javascript, so much confusion over the years due to context binding and the difference between the meaning of this in javascript and this in most of the other OOP languages.
All this leads me to ask, why, why! why would you wan't to rebind an arrow function! Those where created specially to solve all this issues and confusions and avoid having to use bind or call or whatever other way to preserve the scope of the function.
TL;DR
No, you cannot rebind arrow functions.
Short, You CANNOT bind arrow functions, but read on:
Imagine you have this arrow function below which prints this on the console:
const myFunc = ()=> console.log(this);
So the quick fix for this would be using normal function, so just change it to:
function myFunc() {console.log(this)};
Then you can bind it to any lexical environment using bind or call or apply:
const bindedFunc = myFunc.bind(this);
and call it in case of bind.
bindedFunc();
There are also ways to using eval() to do it, which strongly not recommended.
Do ES6 Arrow Functions Really Solve “this” In JavaScript
The above link explains that arrow functions this doesn't change with bind, call, apply functions.
It is explained with a very nice example.
run this in node v4 to see the "expected" behavior,
this.test = "attached to the module";
var foo = { test: "attached to an object" };
foo.method = function(name, cb){
// bind the value of "this" on the method
// to try and force it to be what you want
this[name] = cb.bind(this); };
foo.method("bar", () => { console.log(this.test); });
foo.bar();
I think this is better solution
var f = (vm=this) => console.log(vm);
I asked the same question a couple days ago.
You cannot bind a value since the this is already bound.
Binding different this scope to ES6 => function operator
Maybe this example help to you :
let bob = {
_name: "Bob",
_friends: ["stackoverflow"],
printFriends:(x)=> {
x._friends.forEach((f)=> {
console.log(x._name + " knows " + f);
});
}
}
bob.printFriends = (bob.printFriends).bind(null,bob);
bob.printFriends();
Well it's meant to be impossible to bind an object to an arrow function, never say never; I figured a hack that just might work.
function arrowToRegularFn(callback) {
let _callback = callback
const stringifiedCallback = callback.toString()
const isArrowFn = !stringifiedCallback.trim().startsWith("function")
if (isArrowFn) {
const isParamsInParantheses = stringifiedCallback.trim().startsWith("(")
const [fnParams, ...fnBody] = stringifiedCallback.split("=>")
_callback = eval("(function" + (!isParamsInParantheses ? "(" : "") + fnParams + (!isParamsInParantheses ? ")" : "") + "{" + fnBody.join("=>") + "})")
}
return _callback
}
// test cases
// our object to bind
const quiver = { score: 0 }
let arrow, regular;
// test - 1
arrow = () => this.score++
regular = arrowToRegularFn(arrow).bind(quiver)
regular()
console.log(quiver.score) // 1
// test - 2
arrow = (x, y) => this.score = x + y
regular = arrowToRegularFn(arrow).bind(quiver)
regular(1, 2)
console.log(quiver.score) // 3
// test - 3
arrow = (x, y) => { this.score = x + y }
regular = arrowToRegularFn(arrow).bind(quiver)
regular(3, 4)
console.log(quiver.score) // 7
// test - 4
arrow = function(x, y) { this.score = x + y }
regular = arrowToRegularFn(arrow).bind(quiver)
regular(5, 6)
console.log(quiver.score) // 11
Normal bind:
tag.on("Initialized", function(tag) {
nodeValueChanged(tag, currentNode)
}.bind(currentNode))
Arrow function bind:
tag.on("Initialized", (tag => { nodeValueChanged(tag, currentNode) }).bind(currentNode))
Arrow functions always have this based on its closest non-arrow function irrespective of where it is called. If there is no non-arrow parent it always refers to the global object.
While you are calling the arrow function using call/bind/apply it's doesn't point to the object which you are passing.
var obj = {a:1};
var add=(b)=>{
return this.a + b;
// basically here this.a will be undefined as it's trying to find in one level up which is parents of this function that is window.
}
add.call(obj,2);
So that's why passing object doesn't work in arrow function.

Confusing function in javascript functional programming

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

Nested functions in closure not being called properly in Javascript

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()()();

Categories

Resources