Can I make an outer argument the same as an inner argument? - javascript

I am trying to create a function that returns the sum of all the multiples of 3 or 5 below the number passed in. I immediately recognized the similarity to "FizzBuzz". This is the first codewars challenge. I have created two functions that I have tested and they work independently, but I can't figure out how to reference the argument of the outer function solution() in my inner function returnNumber. Every time I try to run the function, I get an answer of 0.
function solution(number){
function returnNumbers(number){
let numbers=[];
for (let i=1; i<number; i++){
if (i % 3 == 0 && i % 5 == 0) numbers.push(i);
else if (i % 3 == 0) numbers.push(i);
else if (i % 5 == 0) numbers.push(i);
} //end of for loop
return numbers
} //end of returnNumbers
let sum = returnNumbers().reduce(function(a, b){
return a + b;
}, 0);
return sum
} //end of solution
I already tried assigning a new variable for the original argument but maybe I didn't do it correctly. Like this:
function solution(number){
let x = number
function returnNumbers(x){
let numbers=[];
for (let i=1; i<x; i++){
if (i % 3 == 0 && i % 5 == 0) numbers.push(i);
else if (i % 3 == 0) numbers.push(i);
else if (i % 5 == 0) numbers.push(i);
} //end of for loop
return numbers
} //end of returnNumbers
let sum = returnNumbers().reduce(function(a, b){
return a + b;
}, 0);
return sum
}
I imagine the solution is simple, but I am an absolute beginner (< 3weeks) so I would appreciate some help.

The main issue you are facing is scope - how long a variable still "exists". The main thing to realize is that anything in the outer function is still in scope in the inner function, as long as you don't declare a variable with the same name (when you do, the outer variable is shadowed - it still exists, you just can't access it, because when you use that name you'll get the inner one).
So, your first solution is correct, except that you need to not have an argument to the function:
function returnNumbers(number){
should just be
function returnNumbers(){
because number is already in scope, but if you declare it as an argument, you will need to pass it (but that's pointless in this case).

when calling returnNumbers function, argument is not getting passed. Try passing the outer function value to it.
let sum = returnNumbers(number).reduce(function(a, b){
return a + b;
}, 0);

Your inner function already has access to the outer function's parameter (because it's sitting inside of the outer function's brackets). So in your case, returnNumbers can already use number without having it passed as a parameter.
By declaring it as a parameter for returnNumbers, you're shadowing the number variable. You have two possible solutions.
Either pass number to returnNumbers
let sum = returnNumbers(number).reduce(function(a, b){
return a + b;
}, 0);
Or remove returnNumbers parameter
function returnNumbers(){
...
}

Related

Recursive Factorial inside Object Javascript

const Calculate = {
factorial(n) {
return n * factorial(n - 1)
}
}
let newNumber = Calculate.factorial(8);
So every time I call the function I get a factorial not defined error. I'm guessing it has something to do with the function being inside an object. Need some help in understanding whats going on. Thank you in advance
Objects don't create a variable scope, so you need to refer to the object when calling the method.
You can also use this to refer to the object that the method was called on, so you don't have to hard-code the variable name.
const Calculate = {
factorial(n) {
if (n <= 1) {
return 1;
}
return n * this.factorial(n - 1)
}
}
let newNumber = Calculate.factorial(8);
console.log(newNumber);

What do I need a return statement for in JavaScript?

I'm trying to wrap my head around the return statement but I can't see a reason why I should use one. My code works just fine without using one...
In both examples my console prints out 10 not matter if I use return or not.
Without return:
var sum = 5;
function myFunction() {
sum += 5;
}
myFunction();
console.log(sum);
With return:
var sum = 5;
function myFunction() {
return sum += 5;
}
myFunction();
console.log(sum);
By default, functions return the value undefined. If you want the function to return some other value, you need to have a return statement.
You may also use a return statement to halt execution of the function based on some logic, again returning a value that has some meaning or just undefined.
In the first example in the OP, the function is called and the return value is not used for anything, so it doesn't matter what the return value is and a return statement isn't necessary.
In another scenario, the return value might be important, e.g. a function that generates an integer random number between 0 and 10:
function getRandomInteger(){
return Math.floor(Math.random() * 11);
}
function showRandomNumber() {
document.getElementById('s0').textContent = getRandomInteger();
}
<button onclick="showRandomNumber()">Show random number</button>
<span id="s0"></span>
In the above, the getRandomInteger function needs to return a specific value, so it uses a return statement. The showRandomNumber function just displays the random number, so it doesn't need a return statement as the caller (the listener on the button) doesn't care what the return value is.
Here is what is happening with your example:
var sum = 5; //Sets the sum to =5
function myFunction() {
return sum += 5; // += reassigns the global (sum) to 10
}
myFunction();
console.log(sum);
A better example would be this:
sum = 5;
function myFunction() {
var sumOther = sum + 5;
return sumOther;
}
console.log(“sum:” + sum); // 5
console.log(“myFunction:” + myFunction()); // 10
This is how you would get the run of the function and not the global variable ‘sum’
This is because you use (global) variable declared outside the function (function modify it directly so there is no need to return value). However it is not good way of write functions because they are less reusable because they need proper global context to be used. Better is to use something like this:
function myFunction(num) {
return num += 5;
}
var sum = 5;
var result = myFunction(5) ;
console.log(result); // -> 10
this function can be easily used ind different context because it have parameter num and works only on it (function uses only values declared inside its declaration and body)
The trick in your case a is scope of a function. In both cases variable sum is defined in global scope. When you calling the function, it goes through the following steps:
Look whether var sum is defined in current step Since it not defined
inside the function, go one step over and take a look into outer
scope. Yes, it is defined here, start using it.
Perform calculation.
You are using incremental operator sum += 5 so actually it can be
written as sum = sum + 5. If you will look into second case,
you'll notice that variable have increased value now. And since that
variable is taken from global scope, your function just mutates it.
NOTE: At this point no matter whether you are returning something
from function or not. Your function just mutated outer variable.
The last step - exit from function. As I said earlier, return value
matters only if you want to use result of function call directly,
for instance: var result = myFunction()

Is it possible to add a value when returning a function from a recursive function being chained? [duplicate]

I'm trying to solve a puzzle, and am at my wit's end trying to figure it out.
I'm supposed to make a function that works like this:
add(1); //returns 1
add(1)(1); //returns 2
add(1)(1)(1); //returns 3
I know it can be done because other people have successfully completed the puzzle. I have tried several different ways to do it. This is my most recent attempt:
function add(n) {
//Return new add(n) on first call
if (!(this instanceof add)) {
return new add(n);
}
//Define calc function
var obj = this;
obj.calc = function(n) {
if (typeof n != "undefined") {
obj.sum += n;
return obj.calc;
}
return obj.sum;
}
//Constructor initializes sum and returns calc(n)
obj.sum = 0;
return obj.calc(n);
}
The idea is that on the first call, a new add(n) is initialized and calc(n) is run. If calc receives a parameter, it adds n to sum and returns itself. When it eventually doesn't receive a parameter, it returns the value of sum.
It makes sense in theory, but I can't get it to work. Any ideas?
--edit--
My code is just the route I chose to go. I'm not opposed to a different approach if anyone can think of one.
To answer "how dow this work". Given:
function add(n) {
function calc(x) {
return add(n + x);
}
calc.valueOf = function() {
return n;
}
return calc;
}
var sum = add(1)(2)(3); // 6
When add is called the first time, it stores the value passed in in a variable called n. It then returns the function calc, which has a closure to n and a special valueOf method (explained later).
This function is then called with a value of 2, so it calls add with the sum of n + x, wich is 1 + 2 which 3.
So a new version of calc is returned, this time with a closure to n with a value of 3.
This new calc is called with a value of 3, so it calls add with n + x, which this time is 3 + 3 which is 6
Again add returns a new calc with n set to 6. This last time, calc isn't called again. The returned value is assigned to the variable sum. All of the calc functions have a special valueOf method that replaces the standard one provided by Object.prototype. Normally valueOf would just return the function object, but in this case it will return the value of n.
Now sum can be used in expressions, and if its valueOf method is called it will return 6 (i.e. the value of n held in a closure).
This seems pretty cool, and sum will act a lot like a primitve number, but it's actually a function:
typeof sum == 'function';
So be careful with being strict about testing the type of things:
sum * 2 // 12
sum == 6 // true
sum === 6 // false -- oops!!
Here's a somewhat streamlined version of #RobG's great answer:
function add(n) {
function calc(x) { return n+=x, calc; }
calc.valueOf = function() { return n; };
return calc;
}
The minor difference is that here calc just updates n and then returns itself, rather than returning itself via another call to add, which puts another frame on the stack.
Making self-replication explicit
calc is thus a pure self-replicating function, returning itself. We can encapsulate the notion of "self replication" with the function
function self_replicate(fn) {
return function x() {
fn.apply(this, arguments);
return x;
};
}
Then add could be written in a possibly more self-documenting way as
function add(n) {
function update(x) { n += x; }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
}
Parallel to Array#reduce
Note that there is a certain parallelity between this approach to repeatedly calling a function and Array#reduce. Both are reducing a list of things to a single value. In the case of Array#reduce the list is an array; in our case the list is parameters on repeated calls. Array#reduce defines a standard signature for reducer functions, namely
function(prev, cur)
where prev is the "accumulator" (value so far), cur is the new value being fed in, and the return value becomes the new value the accumulator. It seems useful to rewrite our implementation to make use of a function with that kind of signature:
function add(n) {
function reducer(prev, cur) { return prev + cur; }
function update(x) { n = reducer(n, x); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
}
Now we can create a more general way to create self-replication-based reducers based on a reducer function:
function make_repeatedly_callable_function(reducer) {
return function(n) {
function update(x) { n = reducer(n, x); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
};
}
Now we can create add as
var add = make_repeatedly_callable_function(function(prev, cur) { return prev + cur; });
add(1)(2);
Actually, Array#reduce calls the reducer function with third and fourth arguments, namely the index into the array and the array itself. The latter has no meaning here, but it's conceivable we might want something like the third argument to know what "iteration" we're on, which is easy enough to do by just keeping track using a variable i:
function reduce_by_calling_repeatedly(reducer) {
var i = 0;
return function(n) {
function update(x) { n = reducer( n, x, i++); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
};
}
Alternative approach: keeping track of values
There are certain advantages to keeping track of the intermediate parameters the function is being called with (using an array), and then doing the reduce at the end instead of as we go along. For instance, then we could do Array#reduceRight type things:
function reduce_right_by_calling_repeatedly(reducer, initialValue) {
var array_proto = Array.prototype,
push = array_proto.push,
reduceRight = array_proto.reduceRight;
return function(n) {
var stack=[],
calc = self_replicate(push.bind(stack));
calc.valueOf = reduceRight.bind(stack, reducer, initialValue);
return calc(n);
};
}
Non-primitive objects
Let's try using this approach to build ("extend") objects:
function extend_reducer(prev, cur) {
for (i in cur) {
prev[i] = cur[i];
}
return prev;
}
var extend = reduce_by_calling_repeatedly(extend_reducer);
extend({a: 1})({b: 2})
Unfortunately, this won't work because Object#toValue is invoked only when JS needs a primitive object. So in this case we need to call toValue explicitly:
extend({a: 1})({b: 2}).toValue()
Thanks for the tip on valueOf(). This is what works:
function add(n) {
var calc = function(x) {
return add(n + x);
}
calc.valueOf = function() {
return n;
}
return calc;
}
--edit--
Could you please explain how this works? Thanks!
I don't know if I know the correct vocabulary to describe exactly how it works, but I'll attempt to:
Example statement: add(1)(1)
When add(1) is called, a reference to calc is returned.
calc understands what n is because, in the "mind" of the interpreter, calc is a function child of add. When calc looks for n and doesn't find it locally, it searches up the scope chain and finds n.
So when calc(1) is called, it returns add(n + x). Remember, calc knows what n is, and x is simply the current argument (1). The addition is actually done inside of calc, so it returns add(2) at this point, which in turn returns another reference to calc.
Step 2 can repeats every time we have another argument (i.e. (x)).
When there aren't any arguments left, we are left with just a definition of calc. The last calc is never actually called, because you need a () to call a function. At this point, normally the interpreter would return a the function object of calc. But since I overrode calc.valueOf it runs that function instead.
When calc.valueOf runs, it finds the most recent instance of n in the scope chain, which is the cumulative value of all previous n's.
I hope that made some sense. I just saw #RobG 's explanation, which is admittedly much better than mine. Read that one if you're confused.
Here's a variation using bind:
var add = function _add(a, b) {
var boundAdd = _add.bind(null, a + b);
boundAdd.valueOf = function() {
return a + b;
}
return boundAdd;
}.bind(null, 0);
We're taking advantage of a feature of bind that lets us set default arguments on the function we're binding to. From the docs:
bind() also accepts leading default arguments to provide to the target
function when the bound function is called.
So, _add acts as a sort of master function which takes two parameters a and b. It returns a new function boundAdd which is created by binding the original _add function's a parameter to a + b; it also has an overridden valueOf function which returns a + b (the valueOf function was explained quite well in #RobG's answer).
To get the initial add function, we bind _add's a parameter to 0.
Then, when add(1) is called, a = 0 (from our initial bind call) and b = 1 (passed argument). It returns a new function where a = 1 (bound to a + b).
If we then call that function with (2), that will set b = 2 and it'll return a new function where a = 3.
If we then call that function with (3), that will set b = 3 and it'll return a new function where a = 6.
And so on until valueOf is called, at which point it'll return a + b. Which, after add(1)(2)(3), would be 3 + 3.
This is a very simple approach and it meets the criteria the OP was looking for. Namely, the function is passed an integer, keeps track of that integer, and returns itself as a function. If a parameter is not passed - the function returns the sum of the integers passed to it.
let intArray = [];
function add(int){
if(!int){
return intArray.reduce((prev, curr) => prev + curr)
}
intArray.push(int)
return add
}
If you call this like so:
console.log(add(1)(1)());
it outputs 2.

recursive function return different values depending of order when summing array elements

I implemented the following recursive JS function to get the the sum of elements in a array. This function works fine, when input [1,2,3] it returns 6, which is OK.
function sumOfNumbers(array) {
if (array.length == 1) {
return array[0];
} else {
last = array.length - 1;
return array[last] + sumOfNumbers(array.slice(0, last));
}
}
However, when changing the order of the sum to:
return sumOfNumbers(array.slice(0,last)) + array[last];
It returns 5 for [1,2,3]. Does anybody knows why?
Because the variable last is global, and you're changing it with your call to sumOfNumbers(array.slice(0,last)), before this part: array[last] sees it.

JavaScript Closure Issue... Scoping?

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

Categories