JavaScript is kinda weird because it uses lexical scoping for most of the part, but uses dynamic scoping for 'this'.
Lexical scoping looks sane, and it's adopted by most programming languages nowadays. Because it's much easier to reason about - it just worked as how the code was written, in the same file. While dynamic scoping would leak variables everywhere - when you need it it's not there, when you don't want it, it just sneakily replace many variables that you expect to be other things.
But there are still quite some mostly dynamically scoped languages in use like Emacs Lisp, or shell languages like Bash and Powershell. Other than dynamically is debatable faster and easier to implement, it's also handy when you override the environment variables for short shell scripts. But for large codebases it's a nightmare, so traditionally Emacs Lisp scripts have super-long-variable-names-in-order-to-avoid-collisions just like writing CSS, and people had enough now so in newest version people can have a syntax that can enable lexical scoping.