I'm beginner with Javascript and my teacher gave me this code :
var z = (x=>(y=>2*y)(x)+3)(5);
(Sorry for my English, I'm a French guy with a bad level of English ^^)
I have to re-write this code with simple functions but I'm not sure of myself.
For me, I can re-write this code like :
var x = 5;
var y = 2 * x;
var z = y + 3;
But, it's not re-write with simples functions.
My question is : can you help me to understand how arrow function works in this case and give me an idea how to re-write this code with simple functions.
Arrow functions that have a => b form implicitly return b when called. You can imagine them like:
function (a) { return b }
Additionally, your code sample is wrapped in () and immediately invoked, pattern known as the Immediately Invoked Function Expression (IIFE):
(a => b)(3)
which is the same as
(function (a) { return b })(3)
Where both functions get defined and invoked immediately, hence the name.
Now all you have to do is use these two ideas, implicit returns and IIFEs for arrow functions, to re-write your example as plain functions with explicit returns and regular IIFEs.
In other words:
Add return statements where they are assumed to exist (implicit in arrow functions)
Add function() around each arrow function's arguments.
Here's what is happening in your code sample in plain English:
Pass 5 into an IIFE which takes x
Pass that x down to another IIFE which takes y
Return 2 * y from the second IIFE
Add 3 to what was return from second IIFE
Return result from the first IIFE
Or as a math formula:
z = x = (2 * y) + 3
We have:
var z = (x=>(y=>2*y)(x)+3)(5);
The arrow function definition says that x=>(....) means (function(x){ return ...})
So
var z = (function(x) {
return (y=>2*y)(x)+3;
})(5);
We have now another arrow function y=>2*y, that means (function(y) { return 2*y}).
So
var z = (function(x) {
return (function(y) {
return 2*y;
})(x) + 3;
})(5);
And that's all.
Remember that (function(){})() it's an anonymous function declaration executed immediately. So at the end, the var z is a simple number.
Related
This question already has answers here:
What's the meaning of "=>" (an arrow formed from equals & greater than) in JavaScript?
(14 answers)
Closed 6 years ago.
I have the following arrow function
if( rowCheckStatuses.reduce((a, b) => a + b, 0) ){}
rowCheckStatuses is an array of 1's and 0's, this arrow function adds them all up to produce a number. This number acts as a boolean to determine whether or not there is at least one "1" in the array.
The issue is, I don't really understand how arrow functions work, and my IDE thinks it's bad syntax and refuses to check the rest of my document for syntax errors.
How would I go about converting this to a regular function to alleviate both issues?
An arrow function can usually be converted by replacing
(<args>) => <body>
with
function(<args>) { return <body>; }
So yours would be
rowCheckStatuses.reduce(function(a, b) { return a + b; }, 0)
There are exceptions to this rule so it's important that you read up on arrow functions if you want to know all of the differences. You should also note that arrow functions have a lexical this.
You can refactor it as:
if( rowCheckStatuses.reduce(function(a, b){return a + b}, 0)
The initial accumulator isn't necessary (unless you expect the array to be empty sometimes), it could be:
if( rowCheckStatuses.reduce(function(a, b){return a + b})
This number acts as a boolean to determine whether or not there is at least one "1" in the array
It might be faster (and clearer) to use:
if( rowCheckStatuses.some(function(a){return a == 1}))
which will return true if there are any 1s in rowCheckStatuses and will return as soon as one is encountered. Another alternative is indexOf:
if( rowCheckStatuses.indexOf(1) != -1)
Lots of alternatives.
Replacing arrow functions with regular functions is usually unproblematic:
var f = x => y;
var g = function(x) { return y; }
Or, in your specific example:
rowCheckStatuses.reduce((a, b) => a + b, 0);
rowCheckStatuses.reduce(function(a, b) { return a + b; }, 0);
However, be aware of the exceptions:
Arrow functions don't bind a this value. Accessing this in an arrow function might thus return the value of the enclosing execution context's this:
function MyClass() {}
MyClass.prototype.f = () => this;
MyClass.prototype.g = function() { return this; }
myClass = new MyClass();
console.log(myClass.f()); // logs `Window`
console.log(myClass.g()); // logs `myClass`
Arrow functions also don't have access to a local arguments object. Accessing arguments in an arrow function might e. g. return the arguments of an enclosing function:
function test() {
var f = () => arguments;
var g = function() { return arguments; }
console.log(f()); // logs test's arguments
console.log(g()); // logs g's arguments
}
test('x');
The same holds for new.target and super. See also What are the differences (if any) between ES6 arrow functions and functions bound with Function.prototype.bind?
What is the difference of accessing variables inside the function by as argument and without argument?
var a = 1;
var b = 2;
function x() {
var c = a + b;
console.log(c)
}
function y(a, b) {
var c = a + b;
console.log(c)
}
The key difference here is that y does not use anything other than the arguments provided to the function. As soon as you see the function call - say y(1, 2) - you know exactly what will happen. (Assuming at least that you are reasonably familiar with the function and what it does - but even if you aren't familiar with it, hopefully it has a name that makes it sufficiently clear.)
The contrast with x is that it reads from external (here global) variables a and b. In other words, it depends on inputs that are not explicitly provided to the function. This makes it much harder to understand what a call to x() will do, because it depends on the value of a and b - which may be assigned quite some distance away in the program. Indeed, perhaps their values can be changed, in different ways, and by other functions - in which case it is impossible to know exactly what x() will do without carefully studying the entirety of the program up until that call. Again, contrast that with y where we need only look at the call site, and nothing else.
While, in some practical situations, it is hard to avoid some sort of "global state", avoiding it as much as possible, and trying to keep the information that a function needs local to it - as in y - is unquestionably better design. It makes the code much easier to understand, and therefore much less likely to have bugs in it.
Within the scope of your second function, a and b refer to the arguments, not the global variables.
var a = 1
var b = 2
function exampleOne () {
console.log("example 1: ", a, b)
}
function exampleTwo (a, b) {
console.log("example 2: ", a, b)
}
exampleOne()
exampleTwo(3, 4)
exampleTwo()
The 3 cases have different purposes, some non exhaustive:
Inside a function:
Only if the variable have to be unloaded after the function call, unless it be returned
function helloworld() {
const words = ['hello', 'world'];
return words.join(' ');
}
As argument:
Every time you want to use an external value which change the result
function hello(name) {
return 'Hello ' + name;
}
From closure:
In others cases:
// inside a lambda
function upperThan(array, n) {
return array.filter(item => item > n);
}
// use a constant
const HELLO = 'Hi';
function sayHello(name) {
return HELLO + ' ' + name;
}
Javascript always pass by value so changing the value of the variable never changes the underlying primitive (String or number).
If you modify variables inside the function that is passed as argument then it does not change the value of orignal variable(Pass by value).
var a = 1;
var b = 2;
function x() {
var c = a + b;
a = c;
console.log(c)
}
function y(a, b) {
var c = a + b;
var a = c;
console.log(c)
}
y(a, b)
console.log(a)
console.log(b)
x()
console.log(a)
console.log(b)
I'm trying to write a JavaScript function that will integrate functions using Simpson's Rule. I fully understand the math behind Simpson's Rule, but I'm unsure of how to write a function that will integrate another function. Here's the code I'd like to implement:
integrate = function(leftBound, rightBound, numSubIntervals, expression) {
var a = leftBound,
b = rightBound,
n = numSubIntervals,
myFunc = expression;
/*implementation of simpson's rule..*/
return result;
}
My issue is that I don't know how to pass a mathematical expression (the function to be integrated) as a parameter without doing something like passing it as a string and using eval(), which is not something I want to do. I also don't want to use any third-party libraries. I want to write the function using vanilla JavaScript only. What am I missing here - is there an obvious solution to this?
Functions themselves can be arguments to other functions. For example:
integrate(0,5,10, function(x){
return x*x;
})
This example takes a function that takes a given X and squares it. Within integrate, you would call this function for given intervals of x to integrate this function using Simpson's rule.
Within integrate, the syntax for calling a function passed to it is:
var point = expression(x);
Where x is the value passed to the function named expression, and point is the return value of expression.
Here's my answer-version of my comment. You can pass the function as parameter and then call it from inside.
integrate = function(leftBound, rightBound, numSubIntervals, expression) {
var a = leftBound,
b = rightBound,
n = numSubIntervals,
myFunc = expression;
/*implementation of simpson's rule..*/
result = (b-a)/6 * (expression(a) + 4*f* ... );
return result;
}
var toIntegrate = function(x){
return 2*x*x*x - 3*x*x + 2*x - 1;
}
integrate(0, 10, 10, toIntegrate);
I have so far:
function func(f,x) {
alert(f(x));
}
func(function(x) {return x*x;},2);
This works, but i am thinking that passing function(x) {return x*x;}, is excessive and I could just pass x*x, as the idea is that I can supply (pretty much) any function.
I have tried:
function func(f,y) {
g=function() {return f;};
alert(g(y));
}
func(x*x,2);
amongst others, but I can't get it to work. Perhaps if I passed 'x*x' as a string..?
You're correct that the syntax is excessive, but for ES5 and before, that's just how it is.
However, in ES6 you can use the new "arrow function" lambda syntax:
func(x => x * x, 2);
See http://www.es6fiddle.net/i4o5uj2l/
FWIW, the above func isn't great since it only supports unary functions, i.e. those taking a single parameter. You could expand func to use ES6 "spread arguments":
function func(f, ...args) {
console.log(f.apply(this, args));
}
func((x, y) => x * y, 3, 7);
> 21
Well I have a way to do that using eval here http://jsfiddle.net/q5ayoszy/
function func(f,y) {
g=function()
{ x=y;
return eval(f);
};
alert(g(y));
}
func('x*x',2);
Note : I pass the expression as a string and then use it inside the function.
You just need to assign the value of y to the variable x inside the function so the eval evaluates correctly
The only way to do that with a string is by using the infamous eval: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
var x = 2;
var y = eval("x * x"); //y = 4
But using eval is almost always a very bad idea.
You could use currying to break down the process into smaller functions:
function multiply(x) {
return function() {
return x*x;
}
}
var bytwo = multiply(2);
bytwo(); // 4
I'm trying to expand my modest level of JavaScript skills by learning how to use closures. In the code below, I thought I'd see console.log output counting down from 3 to 0. Instead, I'm getting -1, -1, -1, -1.
I know I'm dealing with scoping issues, but that's about it. What's missing? How should this be properly written, and why?
function closure_count_test (number)
{
for (var x = 0; x <= number; x += 1)
{
setTimeout(function() {console.log(number - x);}, x * 1000);
}
}
closure_count_test(3);
Your logic is correct. The problem is that setTimout only considers the latest value of the variables. So the setTimout always get x = 0 since it is the last in the loop.
you can see your desired output if you remove the setTimout function.
x is iterated by the for loop, but the function in setTimeout uses the variable x, which is not interpolated at the time the function is created. This causes it to use whatever the final value of x is (because the setTimeouts execute after the loop completes).
In order to get around this, you have to pass the value of x as it is to the callback of setTimeout. You can call a function that returns another function (the new callback):
for (var x = 0; x <= number; x += 1) {
setTimeout(
(function (x) {
return function () { console.log(number - x) };
})(x)
, x * 1000);
}
This passes x from the outer scope with its current value to the inner scope. The inner function uses whatever value x was when the function was created.
A function is returned to work properly with setTimeout.
http://jsfiddle.net/ExplosionPIlls/QhA3a/
How scoping works in basic words is, it makes variables of a main function, that are referenced in nested functions stay after function ends, and all of these functions can later access them.
In provided example x is a variable defined in the main function, and all nested functions will later be able to reference it. By that time the value of x will be number+1, so your result makes perfect sense. To workaround that, you must avoid referencing the variable of the main function. Here's the normal technique:
function closure_count_test (number)
{
for (var x = 0; x <= number; x += 1)
{
setTimeout(function(x) {
return function() {console.log(number - x);}
} (x), x * 1000);
}
}
What you do here, is you call several nested functions, which have their own x copied as an argument, and each of these have one nested function that will reference that argument via scope.
this works because x being to be localised inside one more closure
function closure_count_test(number) {
for (var x = 0; x <= number; x++) ( // not need {} as here is only one operator
function (x) { //Now x - local variable in anonymous function
return setTimeout(function () {
console.log(number - x);
}, x * 1000);
}(x) // pass x to anonymous function as argument
);
}
closure_count_test(3);