Do function's parameters work like its local variables?

Do a function’s parameters work like its local variables? Why a function can pass its parameters to its inner function call(not nested new functions) but can’t pass it’s local variables?

When a variable is declared in a function, it can’t been seen in another function. For example, myVar is declared in function a and can’t been seen in function b:

function b() {
  console.log(myVar);
}

function a() {
  var myVar = 2;
  b();
}

a(); //-->myVar is not defined

But why a function can pass its parameters to its inner function call (not nested new functions)? Parameters are supposed to be the function’s local variables, aren’t they?

function b(str) {
  console.log(str);
}

function a(str) {
  b(str);
}

a("a's argument"); //->"a's argument"

They are like local variables, and just like local variables, the namespace can be over-ridden. If you re-wrote b() in the following way, you’d get the same output:

function b(b-str) {
  console.log(b-str);
}

What’s happening in my code is that the value of the parameter str in a(str) is being passed as the input to function b(b-str), at which point it is assigned to the parameter b-str.

The same exact process is happening in your code, but since the parameter str in b() has the same name as the variable/parameter str in a(), the variable name is overridden, which means that when Javascript evaluates the variable name str inside of b(), it looks in a different part of RAM than a() would. The way you wrote your code, they happen to store the same value, “a's argument”, but they are not the same variable. Hope that helps!

1 Like

Hi, vipatron. :grinning:Thank you very much! Changing b(str) to b(bStr) makes the question much much clearer. I actually confused myself more by making the two functions’ parameters the same name. :sweat:

I’m learning the scoping part of Javascript at present and I still feel puzzled about the under hood of how a(str) passes its parameter value to b(str).

function b is declared in the global context, so its lexical environment decides its outer scope is global context. That’s why in the first example a( ) would return “myVar is not defined”. Because
when function b is called, it can’t see var myVar = 2 in its own scope or outer scope (global).

function b() {
  console.log(myVar);
}

function a() {
  var myVar = 2;
  b();
}

a(); //-->myVar is not defined

But, following this “scoping” clue, things become weird to me in the second example. If function b's outer scope is global, how can b(str) see the value of str? It looks like in this case, when I call b(str) in a(str), function b's outer scope suddenly becomes the scope of function a.:scream:

function b(bStr) {
  console.log(bStr);
}

function a(str) {
  b(str);
}

a("a's argument"); //->"a's argument"

Just out of curiosity, do you know any other programming languages? Especially C/C++. The understanding you seek is about the true nature of variables and memory addresses in the RAM. “a’s argument” is 12 characters long. Let’s say that we are using ASCII encoding, so each character requires 1 byte of memory. A 12-char string requires 12 bytes of memory. Each variable, regardless of name, that can store that string needs the CPU to reserve a 12-byte block of memory in the RAM. The RAM is like a giant piece of tape, and let’s say the first str variable (Let’s call it a.str), starts at byte 0, and goes through byte 11, and probably needs one more byte to represent the length of the string (but let’s ignore that for now). Since most computers now address memory with 32-bits (4 bytes) at a minimum, that means that, realistically, the characters take bytes 0-11 of the RAM and one more for the length, but a.str “points” to the beginning of the first 128-bit (16 byte) block of memory. Since the function call to a() calls b(), the next memory that needs to be allocated is for b.str. Like before, the minimum amount of memory that is addressable is 4 bytes at a time. So, we have to reserve 16 bytes. So, b.str gets bytes 16-31 of the RAM, but only occupies 12 of those bytes.

Now, here’s where the real answer to your question lies. The CPU doesn’t care what your variable name was. It knows that a.str is “bytes 0-11 of RAM” and that b.str is “bytes 16-27 of RAM”. Now, at first, you may think, “Well, then by naming the variables the same in subordinate functions, I’m only confusing myself.” BUT: If you can visualize what’s going on in the RAM, you can understand variable scope MUCH better, and then a.str and b.str are GOOD names, because they let you and other programmers know that you are passing in copies of the same value into the two areas of RAM, but they are the SAME VALUE that is being passed in, and the meaning of the operation you are programming is much easier to follow.

BTW, in C/C++, this whole discussion is the basis of understanding pointers. So, if you understood what I wrote, pat yourself on the back. Pictures will make it much easier if you wanted to google more.

1 Like

Thank you for your further explanation. Javascript is my first language, so it’s not easy for me to follow all the concepts here. But with your guidance, I definitely feel better about the question.:grinning:

1 Like

Very clear explanation. Thank you Randall. Listening to different views on the same question do help me have a further understanding on coding. :smile:

1 Like

This image might help:

1 Like