Javascript function: change value of a single variable InPlace - javascript

The function reverseArrayInPlace(array) is as per solution in eloquentJS. The reverseArrayInPlace function works, by altering the arrayValue as expected. A similar function written for a single variable does not work as expected. In the code, x should come out as 25, but comes out as 20.
//function from eloquentJS solutions, working as expected
`` function reverseArrayInPlace(array) {
for (let i = 0; i < Math.floor(array.length / 2); i++) {
let old = array[i];
array[i] = array[array.length - 1 - i];
array[array.length - 1 - i] = old;
}
return array;
}
let arrayValue = [1, 2, 3, 4, 5];
reverseArrayInPlace(arrayValue);
console.log(arrayValue);
// working as expected, returns → [5, 4, 3, 2, 1]
// Writing similar function for a single variable
function changeInPlace(a) {
a += 5;
return a;
}
let x = 20;
changeInPlace(x);
console.log(x);
// Not working as expected returns, 20 instead of 25
`
Snippet of the code

Assign changeInPlace to a variable at second last line, and then print that variable in console. It should work.

The problem is that you are returning your calculated variable and not logging it. The one you are logging remains 20.
You must use your function as below :
let variable = changeInPlace(x)
Full code must be like :
function changeInPlace(a) {
a += 5;
return a;
}
let x = 20;
x = changeInPlace(x);
console.log(x);
// x should come out as 25
If for any reason you want to edit a variable value directly, you must access it globally like this:
function changeInPlace() {
x += 5;
return x;
}
let x = 20;
changeInPlace(x);
console.log(x);

For each time you want to change the value in a variable, it needs to be called out again in the form of a declaration. Therefore, output of your function needs to be declared as new value for variable x. Like below:
Your function
// Writing similar function for a single variable
function changeInPlace(a) {
a += 5;
return a;
}
let x = 20;
changeInPlace(x);
console.log(x);
// x should come out as 25
Mine
// Writing similar function for a single variable
function changeInPlace(a) {
return a += 5; // Made a small tweak to your function,
}
let x = 20;
x = changeInPlace(x); // this stores the output of the function in the same variable
console.log(x);
This should give you the desired output, assume this is what you've been asking for if otherwise let me know

Answered by Marijn (author of eloquentJS):
You can't change numbers in JavaScript, only create new ones, so there's no way for a function to change the value of a binding whose value is passes as argument to that function. See for example this section in the book: https://eloquentjavascript.net/04_data.html#h_C3n45IkMhg

Related

trouble understanding call-stack within a function

I currently am learning Javascript and C.S fundamentals, I am completing an assignment which was to create a function that takes a value(num) and outputs the index value within fibonacci numbers.
Example: function(6) outputs 8; because 8 is the 6th number in the fibonacci sequence.
fibonacci numbers: 1,1,2,3,5,8
index position: 1,2,3,4,5,6
below is the solution to the problem.
const fibonacci = function(count) {
let a = 0;
let b = 1;
for (let i = 1; i < count; i++) {
const temp = b;
b = a + b;
a = temp;
}
return b;
};
The part I am having trouble understanding lies within the for-loop, from what I've gathered it seems this is how it's being executed within the call-stack:
execute b + a
store the previousValue of b in temp
a is now equal to temp/previousValue
execute b + a
update value of a...
but what I struggle to understand is why a stores the previousValue of B and NOT the currentValue.
When I envision the call-stack running I expected the output to look something like this;
0,1
1,1
2,2
instead of..
0,1
1,1
1,2
The value of a remains at 1 even though b is now equal to 2, after
temp = b;
b = 1;
a = 1;
b = a + b // 2;
a = temp;
a should be equal to 2 now, but instead it remains at 1; Why?
If I understand you correctly, your misunderstanding is here:
a is now equal to temp/previousValue
The value stored in a does not change until the last operation in the loop body. With the initial values of a=0; b=1;, when the loop body runs,
temp is set to the value of b, so temp=1;
b is set to a+b, so b=1
a is updated with the value in temp, so a=1
At the end of each loop, b holds the next Fibonacci value. The value in a is updated to the previous value only so that it can be used in the next iteration of the loop to calculate the new value of b.

Function in "natural language"

I've made a function "ADD" which modifies the value of a variable :
function ADD(xs, n)
{
var nom_variable = xs;
var XS = eval(xs);
nouvelle_valeur = eval(nom_variable + "=XS+n");
}
var x = 5 ;
ADD("x",5); // now x = 10
I would like that the first argument of the function ADD is x, not "x". Is this possible ?
I want my students to write algorithms in a way similar to natural language.
Thanks !
You can't pass x as if it were a reference, but you could construct a functional reference (or Lens) although you are still not passing x but a variable that is a reference of x.
var x = 5;
var xRef = {
get : function(){
return x;
},
set : function(val){
x = val;
}
}
function add(ref, n){
var oldVal = ref.get();
ref.set(oldVal+n);
}
add(xRef, 5);
console.log(x);
It's definitely not pretty though.

Reducing Multiple Variables in JavaScript

Can I reduce multiple variables in JavaScript?
For example if I have 3 variables:
var foo = 10;
var boo = 15;
var lol = 15;
//Normal syntax:
foo -=1; // -> foo will be 9
boo -=1; // -> boo will be 14
lol -=1; // -> lol will be 14
Is there an option to do it with one line? or better syntax?
For example: foo ,boo ,lol -=1;
No, you cannot. Standard JavaScript does not give this opportunity. The worse thing that you nearly cannot do it functionally as well. lol -=1; or lol--; is just a shortcut for lol = lol - 1;. So if you will try to write a function, which does that for you e.g.:
function reduce() {
for (var i = 0; i < arguments.length; i++) {
arguments[i] = arguments[i] - 1;
}
}
and then call it like
reduce(foo, bar, lol);
it just won't work because you pass primitive numbers (not references). Every time you change the number inside of the function it won't change the number itself but it will return a new number instead.
This could be solved by using some object to store all the variables, e.g.:
var vars = {
foo: 12,
bar: 13,
lol: 14
};
function reduce(variables) {
for (variable in variables) {
if (variables.hasOwnProperty(variable)) {
variables[variable] -= 1;
}
}
return variables;
}
reduce(vars);
But this is not a list of 3 variables, this is kind of a context you attach them to.
If you do the stuff in a global scope (e.g. in a window without wrapping the stuff in a function), you can combine both ways above into one (Window stores all var-declared variables inside):
function reduce(vars) {
var varslist = vars.split(',');
for (var i = 0; i < varslist.length; i++) {
window[varslist[i]] -= 1;
}
}
reduce('foo,boo,lol');
but as soon as you move it to some subcontext it won't work any longer. Also it looks very nasty. I would rather prefer the second solution with vars object representing your variables context.
You can do it with one line, but you still have to repeat the operation:
foo--, bar--, lol--;
Read about the comma operator. It can be useful, but it's usually not very readable.
I wouldn't even combine var statements into 1:
var foo = 1, bar = 2, lol = 3;
because if a var changes, the entire line changes.
I used to do this:
var foo = 1,
bar = 2,
lol = 3;
but that's bad practice too, because deleting foo or lol will change more than just 1 line (because the var prefix or ; suffix).
Sometimes verbosity is good:
var foo = 10;
var boo = 15;
var lol = 15;
foo -= 1;
boo -= 1;
lol -= 1;

Why does it only sums the last two numbers?

I am trying to make a program that sums every number given as parameter. To do so, I wrote the following code:
var x = 0;
var i = 2;
while (isNaN(+process.argv[i + 1]) == false){
x = +process.argv[i] + +process.argv[i + 1];
i++;
}
console.log(x);
The problem is that the code I wrote sums only the 2 last parameter.
I launch my code using node sumArgs.js 1 2 3
and it returns 5.
What is the problem with my code and why isn't it working as planned ?
What is happening every time you loop through, it is taking the current parameter, and the next, and setting x to equal the sum of those.
x needs to be added to, not set. You can do this either:
x += process.argv[i]
or
x = x + process.argv[i]
I'm also not sure why you are adding 2 arguments each loop, as this will cause the sum to be incorrect at the end (unless you increment i twice each loop).
I should note that map reducing it, as in another comment, wouldn't work as the first 2 arguments would not be parameters passed to the program, they would be "node" and "program.js".
var x = 0;
var i = 2;
while (isNaN(+process.argv[i]) == false){
x = x + process.argv[i];
i++;
}
console.log(x);
However, what you could do is use slice:
var sum = process.argv.slice(2).reduce(function(previousValue, currentValue) {
return previousValue + currentValue;
});

Two operation in one function

function test(a, b){
a = a + 2;
b = b + 5;
}
var a = 1;
var b = 2;
test(a, b);
console.log(a);
console.log(b);
This return 1 and 2, but i would like 3 and 7.
Is possible to make two operation in one function? This working if i use return, but how to use return to two operation?
live: http://jsfiddle.net/anCq6/
The reason you are getting 1 and 2 instead of 3 and 7 is because there are two different a and b variables. There's the a and b you declared outside the function, and there is the a and b which represent the values you passed into the function. (Basically, the parameters declared in the function's parentheses are newly declared variables.)
If you want to change the external a and b, change your test function to the following:
function test(x, y) {
a = x + 2;
b = y + 5;
}
Or, alternatively, don't pass a reference into the function, so that the a and b in the inner scope refer to the same a and b as the outer scope:
function test() {
a = a + 2;
b = b + 5;
}
Just send it back as an object...
function test(a, b){
a = a + 2;
b = b + 5;
return {a:a,b:b};
}
var a = 1;
var b = 2;
var test = test(a, b);
alert(test.a);
alert(test.b);
DEMO HERE
This doesn't work because since numbers are passed by value and not by reference, you're modifying the local copies of those variables, however the ones in the outer scope remain unmodified.
If you remove the a and b parameters from your function, you'll get the behavior that you want since the a and b parameters that are being modified will be the ones in the outer scope.
What are references?
Here's a pretty decent answer - Javascript by reference vs. by value
In short, only objects and arrays are passed by reference. Although in reality it's more complex than this depending on how functions are defined and syntax, at this point you can assume that anything that's defined by calling new or the syntactic shorthands [] ( array ) and {} ( object ) are passed by reference. Other types like numbers and strings are passed by value.
Another solution: because of how variable scope works in JavaScript, you can just remove the parameters of "test" function and it will work.
function test(){
a = a + 2;
b = b + 5;
}
function test(){
a = a + 2;
b = b + 5;
}
var a = 1;
var b = 2;
test();
console.log(a);
console.log(b);

Categories

Resources