Javascript functions as values and closure - javascript

I am grappling to understand functions as values, and closure in Javascript.
Consider the code;
function multiplier(factor) {
return function (number) {return number * factor; }
}
var i = multiplier(10);
What is i actually holding at this point? I know I could use i next by doing something like
console.log(i(5));
which would produce the value 50. But I'd still like to know what Javascript actually gives to i before this.

Consider the following two examples. The first you have given and the second one I provided.
In the first one might think that the returned function is
function (number) {return number * 10; }
But this isn't really the case even if it is easy to think of it that way. factor is saved as a reference to the parameter factor. So the function multiplier returns a function with a reference to the value you provided.
If the value of factor changes then the function result is different.
function multiplier(factor) {
return function (number) {return number * factor; }
}
var i = multiplier(10);
console.log('Example1',i(5))
function multiplier2(factor) {
setTimeout(() => {factor = 100}, 1000)
return function (number) {return number * factor; }
}
var i2 = multiplier2(10);
console.log('Example2',i2(5))
setTimeout(() => {console.log('Example2',i2(5))}, 1100)

var i = multiplier(10);
is actually var i = function(number){return number * 10;}
then when calling console.log(i(5));
you are calling
console.log(function(5){return 5* 10;})

i is actually a brand new function: function (number) {return number * 10; }
So if you have j = multiplier(10); actually i is not j, because they are 2 different functions
One more note is that, after i = multiplier(10); you no longer have factor as reference or as value anymore, factor already disappear from your i

Related

How to use Javascript every() method to check one element against all other in an array?

My situation is this, I have a Point object thats has an 'x' and 'y' properties. Point also have a getDistance() method that calculates the distance between two Points.
Example:
if (position.getDistance(prevPosition) > 10) {
// add new Point
} else {
// don't add new Point
}
I have an array of Points and I need to check if the new Point is too close to all the other Points in the array. looking at the Javascript documentation the every() method seems to be the go to function to use but I'm struggling implementing it.
function getDistance(position, prevPosition) {
return position.getDistance(prevPosition) > 10;
}
if (points.every(position)) {
// add new Point
} else {
// don't add Point
}
Any help will be much appreciated
.every takes a function, and every element of the array gets passed to that function (in your case, every point gets passed) and then you have to return a predicate (whether it is far away):
points.every(position => position.getDistance(newPoint) > 10)
This is how you can use the every function:
let a = [1,2,3,4];
let areAllPositive = a.every(num => num > 0); // true
let areAllOdd = a.every(num => num % 2); // false
console.log(areAllPositive);
console.log(areAllOdd);
In your use case, it would be
let allPointsAreFarEnough = points.every(point => point.getDistance(position) > 10)

Fibonacci for large numbers in Javascript

I have the following code:
function fib(n) {
let first=BigInt(0);
let snd=BigInt(1);
let currentNumber;
let countMax=Math.abs(n)+1;
let counter=2;
if(n==0){
return first;
}
else if (n==1||n==-1){
return snd;
}
while(counter<countMax)
{
currentNumber=first+snd;
first=snd;
snd=currentNumber;
counter++;
}
if((n<0) && (n % 2 ==0))
{
return -currentNumber;
}
return currentNumber;
}
That returns the fibonacci number for the given (n).
My issue is that I have to improve the performance of this code. I tried to use different fibonacci formulas (exponential ones) but I lose a lot of precision cause phi number has infinite decimals, so I have to truncate and for big numbers I lost a lot of precision.
When I execute for instance fib(200000) I get the huge number but the code spends more than 12000 ms.
For other hand I tried using recursion but the performance decreases.
Could you provide me an article or clue to follow?
Thanks & Regards.
First of all, you can refer the answer here which says that
Fib(-n) = -Fib(n)
Here's the recursive implementation which is not efficient as you mentioned
function fib(n) {
// This is to handle positive and negative numbers
var sign = n >= 0 ? 1 : -1;
n = Math.abs(n);
// Now the usual Fibonacci function
if(n < 2)
return sign*n;
return sign*(fib(n-1) + fib(n-2));
}
This is pretty straightforward and I leave it without explaining because if you know Fibonacci series, you know what the above code does. As you already know, this is not good for very large numbers as it recursively calculate the same thing again and again. But we'll use it in our approach later on.
Now coming towards a better approach. See the below code similar to your code just a bit concise.
function fib(n) {
if(n == 0)
return 0;
var a = 1;
var b = 1;
while(n > 2) {
b = a + b;
a = b - a;
}
// If n is negative then return negative of fib(n)
return n < 0 ? -1*b : b;
}
This code is better to use when you want to call this function only a few times. But if you want to call it for frequently, then you'll end up calculating the same thing many times. Here you should keep track of already calculated values.
For example, if you call fib(n) it will calculate nth Fibonacci number and return it. For the next time if you call fib(n) it will again calculate it and return the result.
What if we store this value somewhere and next time retrieve it whenever required?
This will also help in calculating Fibonacci numbers greater than nth Fibonacci number.
How?
Say we have to calculate fib(n+1), then by definition fib(n+1) = fib(n) + fib(n-1). Because, we already have fib(n) calculated and stored somewhere we can just use that stored value. Also, if we have fib(n) calculated and stored, we already have fib(n-1) calculated and stored. Read it again.
We can do this by using a JavaScript object and the same recursive function we used above (Yes, the recursive one!). See the below code.
// This object will store already calculated values
// This should be in the global scope or atleast the parent scope
var memo = {};
// We know fib(0) = 0, fib(1) = 1, so store it
memo[0] = 0;
memo[1] = 1;
function fib(n) {
var sign = n >= 0 ? 1 : -1;
n = Math.abs(n);
// If we already calculated the value, just use the same
if(memo[n] !== undefined)
return sign*memo[n];
// Else we will calculate it and store it and also return it
return sign*(memo[n] = fib(n-1) + fib(n-2));
}
// This will calculate fib(2), fib(3), fib(4) and fib(5).
// Why it does not calculate fib(0) and fib(1) ?
// Because it's already calculated, goto line 1 of this code snippet
console.log(fib(5)); // 5
// This will not calculate anything
// Because fib(-5) is -fib(5) and we already calculated fib(5)
console.log(fib(-5)); // -5
// This will also not calculate anything
// Because we already calculated fib(4) while calculating fib(5)
console.log(fib(4)); // 3
// This will calculate only fib(6) and fib(7)
console.log(fib(7)); // 13
Try out some test cases. It's easy to understand why this is faster.
Now you know you can store the already calculated values, you can modify your solution to use this approach without using recursion as for large numbers the recursive approach will throw Uncaught RangeError. I leave this to you because it's worth trying on your own!
This solution uses a concept in programming called Dynamic Programming. You can refer it here.
If you just add the previous value to the current one and then use the old current value as the previous one you get a significant improvement in performance.
function fib(n) {
var current = 1;
var previous = 0;
while (--n) {
var temp = current;
current += previous;
previous = temp;
}
return current;
}
console.log(fib(1)); // 1
console.log(fib(2)); // 1
console.log(fib(3)); // 2
console.log(fib(4)); // 3
console.log(fib(5)); // 5
You can also use an array in the parent scope to store the previous values to avoid redoing the same calculations.
var fibMap = [1, 1];
function fib(n) {
var current = fibMap[fibMap.length - 1];
var previous = fibMap[fibMap.length - 2];
while (fibMap.length < n) {
var temp = current;
current += previous;
previous = temp;
fibMap.push(current);
}
return fibMap[n - 1];
}
console.log(fib(1)); // 1
console.log(fib(2)); // 1
console.log(fib(3)); // 2
console.log(fib(4)); // 3
console.log(fib(5)); // 5
Benchmark for getting the 1000th number 3 times

JS create an array with unique random numbers

Full code looks like this, ideally we have 4 div boxes that need to be randomly filled with random numbers ansValue, one of them (rightAnsValue with its rightAnsId) is already done and works fine, I've managed to make it unique in comparison to others (code without commented section). But met a problem with making others unique, I keep having some identical values in my boxes. In comments is one way I tried to solve this, but pretty sure there is a much simpler and smarter solution that actually works. I would appreciate if you could help to find an understandable solution to this problem.
(P.S. I've seen similar questions but they are either too dificult or done without JS.)
function createAnswers(){
for(ansId=1; ansId<5; ansId++){
if(ansId!=rightAnsId){
for(i=1; i<10; i++){
digitArray[i-1] = i;
}
genNewRandNum();
// ansArray.length = 3;
// ansArray.push(ansValue);
// for(k=0; k<3; k++){
// if(ansArray[k] == ansArray[k+1] || ansArray[k] == ansArray[k+2]){
// genNewRandNum();
// ansArray[k] = ansValue;
// }else if(ansArray[k+1] == ansArray[k+2]){
// genNewRandNum();
// ansArray[k+1] = ansValue;
// }else{
// break;
// }
// }
if(ansValue!=rightAnsValue){
document.getElementById("box" + ansId).innerHTML = ansValue;
}else{
genNewRandNum();
document.getElementById("box" + ansId).innerHTML = ansValue;
}
}
}
}
The way I generate new numbers:
function genNewRandNum(){
rand1 = digitArray[Math.floor(Math.random() * digitArray.length)];
rand2 = digitArray[Math.floor(Math.random() * digitArray.length)];
ansValue = rand1 * rand2;
}
Replace your genNewRandNum() with below code. I have used IIFE to create a closure variable alreadyGeneratedNumbers thats available inside the function generateRandomNumber() thats returned.
So everytime genNewRandNum() is executed, it checks against alreadyGeneratedNumbers to make sure it always returns a unique between 1 and 9.
var genNewRandNum = (function(){
var alreadyGeneratedNumbers = {};
return function generateRandomNumber() {
var min = Math.ceil(1),
max = Math.floor(9);
randomNumber = Math.floor(Math.random() * (max - min + 1)) + min;
if(alreadyGeneratedNumbers[randomNumber]) {
return generateRandomNumber();
} else {
alreadyGeneratedNumbers[randomNumber] = randomNumber;
return randomNumber;
}
}
})();
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
Note: If you call genNewRandNum() for the 10th time it will throw error. So if you have a use case where you would need to reset it after all numbers from 1 to 9 are returned, then you need to add code to handle that
The easiest way to brute-force this is to use accept/reject sampling. You can do something like so:
uniqueRandomNumbers = function(n, nextRandom)
{
var nums = {}; var m = 0;
while(m < n)
{
var r = nextRandom();
if(! nums.hasOwnProperty(r))
{
nums[r] = true; m++;
}
}
return Object.keys(nums);
}
Here I'm using the fact that js objects are implemented as hashmaps to get a hashset. (This has the downside of converting the numbers to strings, but if you're not planning on imediately doing arithmetic with them this is not a problem.)
In order to get four unique integers between 0 and 9 you can then do something like:
uniqueRandomNumbers(4, function() { return Math.floor(Math.random() * 10); })
If you want something a little better than brute force (which probably isn't relevant to your use case but could help someone googling this), one option is to go through each element and either take or leave it with an appropriate probability. This approach is outlined in the answers to this question.

I don't understand function return in javascript

Can anyone explain why javascript return statement is used in function? when and why we should use it?
Please help me.
Why is it used in a function?
1. To return back the results of the function
The return does what is says - it returns back some values to the function caller
function sum(num1, num2) {
var result = number1 + number2
return result
}
var result = sum(5, 6) // result now holds value '11'
2. To stop the execution of the function
Another reason that return is used is because it also breaks the execution of the function - that means that if you hit return, the function stops running any code that follows it.
function sum(num1, num2) {
// if any of the 2 required arguments is missing, stop
if (!num1 || !num1) {
return
}
// and do not continue the following
return number1 + number2
}
var result = sum(5) // sum() returned false because not all arguments were provided
Why we should use it?
Because it allows you to reuse code.
If for example you're writing an application that does geometric calculations, along the way you might need to calculate a distance between 2 points; which is a common calculation.
Would you write the formula again each time you need it?
What if your formula was wrong? Would you visit all the places in the
code where the formula was written to make the changes?
No - instead you would wrap it into a function and have it return back the result - so you write the formula once and you reuse it everywhere you want to:
function getLineDistance(x1, y1, x2, y2) {
return Math.sqrt((Math.pow((x2 - x1), 2)) + (Math.pow(( y2 - y1), 2)))
}
var lineDistance1 = getLineDistance(5, 5, 10, 20);
var lineDistance2 = getLineDistance(3, 5, 12, 24);
it's used to return a value from the function.
Let's say you want a function to do some calculation... for a simple example, like calculate a div box's left position on the browser screen.
you call the function and give it the html selector, then the function 'returns' you the left position value.
You use a return statement for two reasons:
To return a specific value from a function.
To finish the execution of the function before the last line of code in the function.
Without any return value; statement, the function does not return a specific value (technically the return value is undefined).
Without a specific return statement somewhere in the function, the function runs until the last line of code in the function.
Examples:
function add(x, y) {
// return a sum of the two arguments
return x + y;
}
console.log(add(1, 3)); // 4
function findParm(str, key) {
if (!str || !key) {
// invalid parameters, so return null
return null;
}
var pieces = str.split("&");
for (var i = 0; i < pieces.length; i++) {
var loc = str.indexOf(pieces[i] + "=");
if (loc >= 0) {
// when we've found a match, return it and finish execution of the function
return str.slice(loc + key.length + 1);
}
}
// no match found, return null
return null;
}
var str = "user=John&login=yes"
findParam(str, "login"); // "yes"

how to create a loop in a function with another function?

I'm new to Java and I'm doing a uni course. I've been asked to design three functions.I have to find the difference between each adjacent numbers in an array, another to total the array and the last one to calculate the difference using the other functions then write a programme. I'm totally lost on the last function and my tutor has gone away on hols. Here is the code I have done so far. I don't want people doing the code for me but if anyone can advice me what I need to do I would appreciate your advice. I'm not sure how to loop the difference function into the array and store it into the new array I have made. If anyone could explain where I am going wrong I would love to hear from you!
var numberArray = [10,9,3,12];
// function difference will find the highest value of the two numbers,find the difference between them and return the value.
function difference(firstNumber, secondNumber)
{
if (firstNumber > secondNumber)
{
return (firstNumber - secondNumber);
}
else
{
return (secondNumber - firstNumber);
}
}
// function sum will add the total numbers in the array and return the sum of numbers.
function sum(numberArray)
{
numberTotal = 0
for (var total = 0; total < numberArray.length; total = total + 1)
{
numberTotal = numberTotal + numberArray[total]
}
{
return numberTotal
}
/*code the process that calculates a new array containing the differences between all the pairs
of adjacent numbers, using the difference() function you have already written.
This function should be named calculateDifferences() and should accept an array numberArray.
The function should first create a new empty array of the same size as numberArray
It should then calculate the differences between the pairs of adjacent numbers,
using the difference() function, and store them in the new array. Finally, the function should return the new array.
The calculation of the differences should be done in a loop, at each step finding the difference between each
array element and the next one along in the array, all except for the last difference,
which must be dealt with as a special case, because after the last element we have to wrap round to the start again.
So the final difference is between the last and first elements in the array.*/
function calculateDifferences()
var createArray = new Array (numberArray.length);
{
createArray = 0;
for (var c = 0; c < numberArray.length; c = c + 1)
{
createArray = difference(numberArray[c]);
}
{
return createArray
}
}
your implementation of function "calculateDifferences" is not correct.
this function should look like this:
function calculateDifferences()
{
var createArray = new Array (numberArray.length);
for (var c = 0; c < numberArray.length - 1 ; c = c + 1)
{
/*
because of the function "difference" has two parameters (firstNumber, secondNumber) in its declaration, we should give two arguments. (that are adjacent elements in array)
*/
createArray[c] = difference(numberArray[c],numberArray[c+1]);
}
/ *
calculating difference of first and last element of array and
assign it to returning array's last element.
*/
createArray[numberArray.length - 1] = difference(numberArray[0],numberArray[numberArray.length - 1]);
return createArray;
}
You should index createArray the same way you already do with numberArray[c].

Categories

Resources