3

As shown in the JS snippet below, arguments[0] and a always keep the same value. This is well-known in JS, but I'm still curious how this is implemented.

For example, if both a and arguments[0] are referencing to the same JS object, it's understandable that they always get the updated value. But this cannot explain the situation for primitive values like 1.

If I understand correctly, JS always copies the value for primitives which implies that both a and object[0] hold a copy of this value. If this is the case, how are a and arguments[0] always synced?

function func(a, b) {

  console.log("a = " + a);
  console.log("arguments[0] = " + arguments[0]);

  arguments[0] = 123;
  console.log("a = " + a);
  console.log("arguments[0] = " + arguments[0]);

  a = 123456;
  console.log("a = " + a);
  console.log("arguments[0] = " + arguments[0]);
}

func(1, 2);

Here is the output:

>node test.js
a = 1
arguments[0] = 1
a = 123
arguments[0] = 123
a = 123456
arguments[0] = 123456
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
hackjutsu
  • 8,336
  • 13
  • 47
  • 87
  • `arguments` is a special object that hooks into the Javascript internals of how local variables are stored. – Barmar Jul 08 '16 at 21:14
  • Thanks Barmar:) Does the term JS internals here means the C++ JS engine? Even in C++, it's still expensive to keep track of several copies of primitive value. One possible guess is the JS primitive is mapped to an object. – hackjutsu Jul 08 '16 at 21:19
  • `JS always copies the value for primitives` - fairly certain you're talking about [passing by value](https://snook.ca/archives/javascript/javascript_pass). Passing by value means changes to `a` _inside_ the function have no relationship to any `a` _outside_ the function. It says nothing about how `arguments` and `a` are connected, which is probably by reference. – Akshat Mahajan Jul 08 '16 at 21:21
  • The JS syntax doesn't seem to allow mapping two JS variable to the same primitive memory block. (Correct me if I'm wrong.) Maybe the situation here goes beyond the normal JS or even implemented in engine's C++/C layer. – hackjutsu Jul 08 '16 at 21:42

2 Answers2

1

The arguments object is special, it hooks into the way the Javascript implementation stores the function arguments. So when you assign to arguments[n], it actually finds the memory block used to hold the parameter variables, and puts the value you're assigning there. And that same memory location is also used when referencing the parameter variables by name.

Another way to think about it is that every function has a local arguments array-like object. When the JS implementation compiles the function definition, it replaces all the parameter variables with references to that array. So expressions that use a are compiled as if they'd used arguments[0], b is translated to arguments[1], and so on.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Both the `arguments` object and named variable are stored in the `Variable Object` inside the `Execution Context`. Unless the creation of `Execution Context` involves something that beyond the normal JS, I find it hard to understand two JS variables can be mapped to the same primitive memory block. Does it suggest that the `Execution Context Stack` is operated in the C++ layer. – hackjutsu Jul 08 '16 at 21:39
  • It's internal to the implementation, it can involve anything the designer wants. – Barmar Jul 08 '16 at 21:43
  • What C++ layer? Javascript is compiled to machine code. – Barmar Jul 08 '16 at 21:43
  • Execution context is a concept, not something visible. – Barmar Jul 08 '16 at 21:44
  • Not very familiar with JS engine. Maybe you are right, C++/C doesn't get involved here. I was thinking there should some low level language to back this memory management. – hackjutsu Jul 08 '16 at 21:45
  • Remember, Javascript is a language specification, not any particular implementation. It just describes what the code does, not how the implementation achieves that result. – Barmar Jul 08 '16 at 21:45
0

"The arguments object is an Array-like object corresponding to the arguments passed to a function." from MDN: Arguments object

To keep it simple, just think.

function func(a, b) {
  // imagine this line of code gets automatically added
  // var arguments = [a, b];

  console.log("a = " + a);
  console.log("arguments[0] = " + arguments[0]);

  arguments[0] = 123;
  console.log("a = " + a);
  console.log("arguments[0] = " + arguments[0]);

  a = 123456;
  console.log("a = " + a);
  console.log("arguments[0] = " + arguments[0]);
}
Alan Dong
  • 3,981
  • 38
  • 35
  • Understood. The magic thing is how `arguments[0]` and the named variable `a` mapped to the same primitive memory block. As explained by @Barmar, this seems to involve implementation details in JS Internals. – hackjutsu Jul 08 '16 at 22:09