Local variable instead parameter in function, better understanding of functions - javascript

Had troubles choosing title. I am learning js and looking for place to ask questions, most of the time they are simple. Is stackoverflow a good place for that or can you recommend another place (irc or forum)?
Begann to work with functions in js. These lines are given:
function calculateTax(amount){
let result = amount * 0.08;
return result;
}
let tax = calculateTax(100);
console.log(tax);
I ask my self why function needs a local variable "result", why couldn't the parameter be used:
function calculateTax(amount){
amount * 0.08;
return amount;
}
let tax = calculateTax(100);
console.log(tax);
My guess is because the parameter is a placeholder or is a variable needed to safe the multiplication and the 0.08? I think I read that parameters are variables to, is this correct? Is the 100 in the function a parameter too?
I think I waste to much time on such things. My problem is, I am to curious.
Thank you for your time.

Assuming that amount is a number, then either method works. That said, reassigning a paraneter when one doesn't have to is generally considered to be a bit of a code smell - see see no-param-reassign.
In your original code, both amount and result are local variables. (yes, parameters are variables too)
Of course, an alternative to declaring a new variable or reassigning amount is to simply return the result of the calculation immediately:
function calculateTax(amount) {
return amount * 0.08;
}
let tax = calculateTax(100);
console.log(tax);
Primitives are immutable, so changing amount inside the function won't cause any side-effects. If amount wasn't a primitive, then you would have to worry about changing it. For example, if it was an object with a value property, then if you changed that property inside the function, the object that was passed in will be mutated. To illustrate:
function calculateTax(obj) {
obj.amount *= 0.08;
return obj.amount;
}
const item = { amount: 100 };
let tax = calculateTax(item);
console.log(tax);
// item was mutated inside the function:
console.log(item);

The reason for introducing a variable is that in many cases what you want a function to do with a parameter isn't quite as simple as in your example. For example another function might take the parameter, send it wrapped in an object, stringified to JSON to a REST service, await the response from that server, and do some calculations on that, and in the end, return it.
In your case I'd even advocate omitting the extra creation of a variable because what the function does is so trivial.

Glad you're learning JavaScript. For more terse syntax (and up your game), use ES6 arrow function notation as follows
const calculateTax = (amount) => amount * 0.08;
console.log(calculateTax(100));

Related

Double Function Call or storing the Result as a variable?

Assume I have some function f(-) defined elsewhere. I use it twice in the following type of code:
if (f(-) satisfies some condition) {
do some stuff
if (f(-) satisfies some other condition) {
do some other stuff
}
}
When the code is run, is f(-) calculated twice (or is the interpreter "intelligent" enough to see that it is enough to calculate it once)? If so, is it recommended to define a constant x = f(-) before that code and use that instead of f(-)? Usually I do this, but I am not fully sure if it is necessary, in particular, when f(-) can be computed really fast.
In case it matters, the language is JavaScript.
if (f(-) satisfies some other condition) will call the same function and it may never enter the block followed by this if, since the function satisfies the outer if that is why it entered into that block.
Create a const and depending on that value execute next step
const isFunResult = f(-);
// expecting this function gives a boolean
if(isFunResult){
// code goes here
}
else{
// code goes here
}
You can also use switch statement if function return multiple result .
In short words, the interpreter is not "intelligent" enough to see that it is enough to calculate it once. So it will call the function twice.
What you are looking for is something called memoization which is used to optimize performance for computational heavy functions to be remembered when the same parameters are passed.
If you need memoization, you could either implement that yourself in your own functions or you could use a javascript framework that supports that. Like React has the useMemo hook.
See https://reactjs.org/docs/hooks-reference.html#usememo
Usually you wont need that and just storing the result of the function in a variable will be enough for most use cases.
Run this to see the examples. Even if the conditions are the same.
function test_me() {
console.log("I got called");
return 99;
}
if (test_me() == 99) console.log("n=99"); // 1st function call
if (test_me() == 99) console.log("n=99"); // 2nd function call
// is different from the following
var n = test_me(); // function called once
if (n == 99) console.log("n=99"); // 1st test
if (n == 99) console.log("n=99"); // 1st test
To answer your question: Yes, it calculates function f(-) TWICE.
More than it is the intelligence of the interpreter, it is the intent of the programmer. The same function can be called twice if the programmer thinks that the function might return a changed value the second time. i.e: if the function uses a new Date() inside the function...
But, if the programmer knows that it is the same output both times (as in your case), it is better to define a constant x = f(-) and reuse it. This will improve performance (if the function is heavy), and improves code maintainability.
Even if it is a compiler, the compiler might not be intelligent enough to detect this, unless the function is a very simple code. But as #perellorodrigo mentioned, you can use memoization, but it is beyond the scope of this answer.
To wrap up, if you call the same function twice, it will be evaluated twice.

Javascript string

I have got a method which finds a required value in an array.
let result = arrayStart.find(obj => obj.data === `${constValue1}/${constValue2}/${constValue3}`)
Will JavaScript create each time a new string in each iteration, e.g.
`${constValue1}/${constValue2}/${constValue3}`
or will it create only once?
JavaScript is not a compiled language, it is interpreted as it runs. This means that there is no sure-fire way for the engine to know what constValue's are in advance, even if they are declared const. This means that in order to know what the final value of the string is, the interpreter has to re-compute it every time.
Normally I would write such code like this:
const searchTerm = `${constValue1}/${constValue2}/${constValue3}`;
let result = arrayStart.find(obj => obj.data === searchTerm);
However, keep in mind that in terms of performance, this requires scope resolution (the engine needs to find where the value searchTerm is defined), so that takes a tiny bit of time as well.
Also, some smarter code processors (i.e. minimizers) might be able to see that this value never changes and extract it in the same manner, but I would not count on that.
The string will be created each time, think of find as a loop that will loop through each element in an array and on each iteration you are constructing a string. I wouldn't worry too much about it as its not being assigned to any variable you are just using it for equality but if you want to make it better i would create a variable outside the callback passed to find and assign it there and use that variable for equality.
such as:
const newString = `${constValue1}/${constValue2}/${constValue3}`;
let result = arrayStart.find(obj => obj.data === newString)

how do javascript functions parameter work under the hood

I'm new to programming and am unable to find any good explanation on parameter/arguments, how they work under the hood. For eg:
function changeStuff(a) {
return a = a * 10;
}
var num = 10;
console.log(changeStuff(num)); //prints 100
console.log(num); //prints 10
When I call this changeStuff function, how does javascript put variable num into parameter - a? Does it do something like a = num under the hood?
I'm sorry if its a bad or a dumb question.
You would need to see compiled code rather than this interpreted code to understand it more, as you donĀ“t even deal with registers here.
Assuming it works same way as c++ (probably similar), when calling a function, function parameters are pushed onto current stack. Then the function reads values from the stack according to the amount and function reads/writes those values.
In compiled code, there will not exist such thing as 'a' variable. Only a limited amount of registers are available, so a will actually be one of those. Before assigning that, the value from the register will be pushed onto the stack, so that when function ends, the register can go back to its previous value for the running code that might have been using it before calling the function.
A bit of literature on the subject
Javascript copies the reference to the function a * 10 to the variable a in this case. So a is a * 10 then and so a * 10 will evaluated and returned.

Javascript recursive function inside a for loop

var f_drum_min = function myself(a){
alert(a);
$f_min_node.push(a);
for (i=0;i<=$m;i++){
if ($f_leg[i][1]==a){
myself($f_leg[i][0]);
}
}
};
myself($f_leg[i][0]); breaks the for loop , how can I make it run multiple times in loop?
Your function is riddled with bad habits
There's no way for me to improve this function because I have no idea what all of those external states do. Nor is it immediately apparent what their data types are.
These are bad habits because there's no possible way to know the effect of your function. Its only input is a, yet the function depends on $f_min_node, $f_leg, and $m.
What is the value of those variables at the time you call your function?
What other functions change those values?
I assigned $f_min_node to some value and then called f_drum_min. How was I supposed to know that $f_min_node was going to get changed?
Every time you call your function, it's a big surprise what happens as a result. These are the woes of writing non-deterministic ("impure") functions.
Until you can fix these problems, recursion in a for-loop the least of your concerns
I have annotated your code with comments here
// bad function naming. what??
var f_drum_min = function myself(a){
// side effect
alert(a);
// external state: $f_min_node
// mutation: $f_min_node
$f_min_node.push(a);
// leaked global: i
// external state: $m
for (i=0;i<=$m;i++){
// external state: $f_leg
// loose equality operator: ==
if ($f_leg[i][1]==a){
myself($f_leg[i][0]);
}
}
};
I can help you write a deterministic recursive function that uses a linear iterative process though. Most importantly, it doesn't depend on any external state and it never mutates an input.
// Number -> Number
var fibonacci = function(n) {
function iter(i, a, b) {
if (i === 0)
return a;
else
return iter(i-1, b, a+b);
}
return iter(n, 0, 1);
}
fibonacci(6); // 8
for loops are pretty primitive; Imperative programmers will reach for it almost immediately thinking it's the only way to solve an iteration problem.
I could've used a for loop in this function, but thinking about the problem in a different way allows me to express it differently and avoid the for loop altogether.
One basic problem with the code, which would cause it to break under almost any circumstances, is that the loop variable i is a global, and is thus shared by all recursive invocations of the function.
For example, let's say the function is invoked for the first time. i is 0. Now it recurses, and let's say that the condition in the if is never true. At the end of the 2nd call, i = $m + 1. When you return to the first call, because i is global, the loop in the first call ends. I assume this is not what you want.
The fix for this is to declare i as local:
for (var i=0;i<=$m;i++){
This may or may not fix all of your problems (as pointed out in comments, we'd have to see more of your code to identify all possible issues), but it is a critical first step.

Why is this javascript necessary?

I was reading the source code for pallet.js and came across this.
var ret = (function(proto) {
return {
slice: function(arr, opt_begin, opt_end) {
return proto.slice.apply(arr, proto.slice.call(arguments, 1));
},
extend: function(arr, arr2) {
proto.push.apply(arr, arr2);
}
};
})(Array.prototype);
var slice = ret.slice;
var extend = ret.extend;
Why is this necessary? Why could they not simply write this:
var slice = function(arr,opt_begin,opt_end) {
return Array.prototype.slice.apply(arr,[opt_begin,opt_end]));
}
var extend = function(arr,arr2) {
return Array.prototype.push.apply(arr,arr2);
}
EDIT 1:
In response to the duplicate question. I don't think it is a duplicate, but that question definitely does address my question. So it is an optimization. But won't each one only be evaluated once? So is there really a significant improvement here for two function calls?
Also if we are worried about performance why are we calling proto.slice.call(arguments,1) instead of constructing the array of two elements by hand [opt_begin,opt_end], is slice faster?
Because the syntax is just so much cooler. Plus you can rationalize it's use by telling yourself that it's more DRY. You didn't have to type Array.prototype twice.
I can't be sure what was the original rationale behind that code (only the author knows) but I can see a few differences:
proto is a closed-over local variable, while instead Array is a global. It's possible for a smart enough Javascript engine to optimize access because proto is never changed and thus it could even be captured by value, not reference. proto.slice can be faster than Array.prototype.slice because one lookup less is needed.
passing opt_begin and opt_end as undefined is not the same as not passing them in general. The called function can know if a parameter was passed and happens to be undefined or if instead it wasn't passed. Using proto.slice.call(arguments, 1) ensures that the parameters are passed to slice only if they were actually passed to the closure.

Categories

Resources