how do javascript functions parameter work under the hood - javascript

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.

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.

5.2 Eloquent Javascript - 3rd Edition

Relatively new at programming, looking for an explanation of a question in Chapter 5 of Eloquent Javascript.
Your own loop Write a higher-order function loop that provides something like a for loop statement. It takes a value, a test
function, an update function, and a body function. Each iteration, it
first runs the test function on the current loop value and stops if
that returns false. Then it calls the body function, giving it the
current value. Finally, it calls the update function to create a new
value and starts from the beginning.
When defining the function, you can use a regular loop to do the
actual looping.
loop(3, n => n > 0, n => n - 1, console.log); // → 3 // → 2 // → 1
The answer:
function loop(start, test, update, body) {
for (let value = start; test(value); value = update(value)) {
body(value);
}
}
loop(3, n => n > 0, n => n - 1, console.log);
// → 3
// → 2
// → 1
Looking for a walkthrough of what the code is doing. Any help to clearly understand this problem would be helpful.
A for loop consists of 4 parts:
Initialization - this is run at the beginning of the loop; it usually initializes the variable(s) used in the Condition and Repetition parts.
Condition - This is executed before each iteration. If its value is truthy, the body is then executed; otherwise, the loop stops immediately.
Repetition - This is executed after each body execution, and usually updates variable tested by the Condition.
Body - This is just ordinary code that's executed each time through the loop. It usually makes use of the variable(s) updated by the other parts.
The syntax is:
for (Initialization; Condition; Repetition) {
Body
}
So in your example, the Initialization sets the current loop value (the value variable) to the value that was given to the function.
The Condition then executes test(value) function. The for loop will automatically test whether this returns true or false -- if it returns false the loop stops. This fulfills the requirement:
Each iteration, it first runs the test function on the current loop value and stops if that returns false.
Then the Body is executed, and this executes body(value). This implements the requirement:
Then it calls the body function, giving it the current value.
Then the Repetition executes value = update(value), which implements:
Finally, it calls the update function to create a new value and starts from the beginning.
"For loops" are a built-in feature common to programming languages, including JavaScript. The Wikipedia article about them is pretty thorough, and I'd start there if you wanted to understand the context of the question.
The exercise at hand, then, is to write a function in JavaScript that roughly-speaking provides similar features to the built-in "for loop".
The solution you quoted defines a function ("loop") that accepts four parameters: an initial value ("start"); a function that runs at before each iteration, to test whether the loop should stop ("test"); a function that will be run after each iteration ("update"); and the function that should be run in the body of the loop during each iteration ("body"). It then uses an actual for loop to perform the requested iterations.
Trying to understand this myself while reading this...but from what I grasp from it it sounds like the author is trying to teach you one of two things.
That a for loop consists of a
for(initialExpression; condition; incrementExpression){
and then the statement
}
That you can create your own reusable customizable loop function that can function like forEach() or how ever you would like it to function.
Solving this with a for loop seems awkward, I understand why you are confused, just like me - I'm noob too :)
Here's a recursive solution, hopefully it will shed more light, if you haven't completely figured stuff out:
function loop(value, test, update, execute) {
if (!test(value)) return; // stop
execute(value);
return loop(update(value), test, update, execute);
}

Local variable instead parameter in function, better understanding of functions

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

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.

JavaScript optimizations: how to cache local variables' initial values more efficiently?

I'm just curious. Maybe someone knows what JavaScript engines can optimize in 2013 and what they can't? Any assumptions for nearest future? I was looking for some good articles, but still there is no "bible" in the internet.
Ok, let's focus on single quesiton:
Suppose I have a function which is called every 10ms or in a tight loop:
function bottleneck () {
var str = 'Some string',
arr = [1,2,3,4],
job = function () {
// do something;
};
// Do something;
// console.log(Date.getTime());
}
I do not need to calculate the initial values for variables every time, as you see. But, if I move them to upper scope, I will loose on variable lookup. So is there a way to tell Javasript engine to do such an obvious thing - precalculate variables' initial values?
I've careated a jsperf to clear my question. I'm experimenting with different types. I'm especially interested in functions and primitives.
if you need to call a function every 10ms, and it's a bottleneck, the first thought you should have is "I shouldn't call this function every 10ms". Something went wrong in the architecting you did. That said, see 1b in http://jsperf.com/variables-caching/2, which is about four times faster than your "cached" version - the main reason being that for every variable in your code, you're either moving up scope, or redeclaring. In 1b, we go up scope once, to get "initials", then set up local aliasses for its content, from local reference. Much time is saved.
(Concerns V8)
Well the array data itself is not created but an unique array object needs to be created every-time. The backing array for the values 1,2,3,4 is shared by these objects.
The string is interned and it is actually fastest to copy paste same string everywhere as a literal rather than referencing some common variable. But for maintenance you don't really want to do that.
Don't create any new function inside a hot function, if your job function references any variables from the bottleneck function then first of all those variables will become context allocated and slow to access anywhere even in the outer function and it will prevent inlining of the bottleneck function as of now. Inlining is a big deal optimization you don't want to miss when otherwise possible.

Categories

Resources