Why is accessing a variable using window.variable slower?

Javascript is terrible for optimization because of eval (that can access the local frame!).

If however the compilers are smart enough to detect that eval plays no role then things can get a lot faster.

If you only have local variables, captured variables and global variables and if you can assume no messing up with eval is done then, in theory:

  • A local variable access is just a direct access in memory with an offset from the local frame
  • A global variable access is just a direct access in memory
  • A captured variable access requires a double indirection

The reason is that if x when looked up results in a local or in a global then it will always be a local or a global and thus it could be accessed directly say with mov rax, [rbp+0x12] (when a local) or mov rax, [rip+0x12345678] when a global. No lookup whatsoever.

For captured variables things are slightly more complex because of lifetime issues. On a very common implementation (with captured variables wrapped up in cells and cell address copied when creating closures) this will require two extra indirection steps… i.e. for example

mov rax, [rbp]      ; Load closure data address in rax
mov rax, [rax+0x12] ; Load cell address in rax
mov rax, [rax]      ; Load actual value of captured var in rax

Once again no “lookup” needed at runtime.

All this means that the timing you are observing is a consequence of other factors. For the mere variable access the difference between a local, a global and a captured variable are very tiny compared to other issues like caching or implementation details (e.g. how the garbage collector is implemented; a moving one for example would require an extra indirection for globals).

Of course accessing a global using the window object is another matter… and I’m not very surprised it takes longer (window is required to be also a regular object).

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)