The reason for the error message is that let and const declarations are both block-scoped, which means that they are only accessible within the { } surrounding them. So because of const or let the variable (arg) from the outer scope won't be accessed if another variable (arg) inside a block scope gets defined.
Or in other words: The variable arg inside a parentheses or curly brackets is not the same as the arg you pass to the function because you make use of let or const inside.
While parsing the block scope the engine already reserves the name for EVERY variable defined inside. But they will only be accessible after the declaration and evaluation using const or let.
So reading it, while writing to it, causes the error you see.
var variable;
{ // [block/env start]
let variable = variable; // ReferenceError: Cannot access 'variable' before initialization
} // [block/env end]
What happens during let variable = variable is that it has to read the right hand side before it assigns the value/reference to the left hand side, but per definition the variable is not available before declaration, therefor it throws the error.
Another example would be:
var variable;
{
console.log(variable); // ReferenceError: Cannot access 'variable' before initialization
let variable;
}
The execution order is similar to the assignment in your example and throws the same error. It won't access the outer variable because another variable gets defined inside that block scope using let/const.
You can also take a look of the Let and Const Declarations.
let and const declarations define variables that are scoped to the running execution context's LexicalEnvironment. The variables are created when their containing Environment Record is instantiated but may not be accessed in any way until the variable's LexicalBinding is evaluated. A variable defined by a LexicalBinding with an Initializer is assigned the value of its Initializer's AssignmentExpression when the LexicalBinding is evaluated, not when the variable is created. If a LexicalBinding in a let declaration does not have an Initializer the variable is assigned the value undefined when the LexicalBinding is evaluated.