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
4
  • arguments is a special object that hooks into the Javascript internals of how local variables are stored.
    – Barmar
    Commented Jul 8, 2016 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
    Commented Jul 8, 2016 at 21:19
  • JS always copies the value for primitives - fairly certain you're talking about passing by value. 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. Commented Jul 8, 2016 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
    Commented Jul 8, 2016 at 21:42

2 Answers 2

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.

6
  • 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
    Commented Jul 8, 2016 at 21:39
  • It's internal to the implementation, it can involve anything the designer wants.
    – Barmar
    Commented Jul 8, 2016 at 21:43
  • What C++ layer? Javascript is compiled to machine code.
    – Barmar
    Commented Jul 8, 2016 at 21:43
  • Execution context is a concept, not something visible.
    – Barmar
    Commented Jul 8, 2016 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
    Commented Jul 8, 2016 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]);
}
1
  • 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
    Commented Jul 8, 2016 at 22:09

Not the answer you're looking for? Browse other questions tagged or ask your own question.