True lexical scoping means that
int foo() {
int a = 3;
{ int a = 2; }
return a;
}
declares two different variables named a, and foo() returns 3.
Javascript notably did not have lexical scoping when it was invented. Until the introduction of `const` and `let`, it only had function scoping -- any variable declared with the `var` keyword within a function is scoped to the entire function, even if you were to declare it within a smaller code block.
Yes, you could implement generalized lexical scoping in Blockly, if you REALLY wanted to. The issue that arises is that you would then have to have blocks for declaring variables, and users would be responsible for explicitly making use of them. This rather defeats the point of Blockly, if you ask me -- sure, you could use Blockly as just a visual overlay that maps token-for-token onto the target language's code, but at that point there's really not a whole lot of reason not to just use text. Blockly shines brightest when the user can focus on logic and ideas instead of having to worry about syntax. It's explicitly a design philosophy that Blockly shouldn't have a notion of syntax errors.
Function scoping is much simpler. You only have two scopes to worry about: local and global. In an environment such as Blockly, this means that one possible implementation would be to have one type of block for local variables, and one type of block for global variables.
This is SORT OF like Blockly's handling of function parameters. Function parameters get put in the pool of global variables, but then they get treated like function-scoped local variables when you use them at run time. I do think for Blockly's primary target use case that this is the right decision: while it's possible that this behavior could be a little confusing to novices defining functions for the first time, it's a simple enough concept to get an intuition for. It's less cognitive overhead than trying to learn about two different kinds of variables. But it's not good enough for programs with recursive functions -- for non-recursive functions you can just use different "global" variable names to store local values that shouldn't get stomped on, but for recursive functions there's simply no way to make that work without proper local variables.
/s/ Adam