I was rather shocked today to discover that since their introduction in ES2015 let, const, class and other new binding forms have allowed undefined to be used as a local binding identifier. Even in strict mode.
I think this was an oversight in ES2015. In ES5 we made the global property "undefined" non-configurable and non-writable. But we did not prevent var and function declarations from binding undefined. This was necessary because there were widely used coding patterns where the mutability of the global "undefined" property was mitigated by usingvar to redeclare undefined.
But, let/const/class were new constructs in ES2015 and that backwards compat constraint should not have applied to them.
I don't know if we could get away with fixing this now but I think we should at least investigate the possibility.

I am in chrome 53,my test shows that they can't.
Sorry,I am not a member,I don't know much details about you say of the spec,just hope that this will helps.
@NE-SmallTown, at the top level they're prohibited because they're restricted globals. Allen is observing that they're not restricted elsewhere: { let undefined; } is legal.
@bakkot Sorry for the cursory test.I test again,Allen is right,it does questionable.
I recall raising this back in the day but the thinking was it's fine since you can't redeclare undefined and you can only look up to an undefined binding in your own code (so it is much less bad than ye olde undefined = true). I'm ok fixing it still :)
It seems similar, to the strict mode restriction on redeclaring eval and arguments. It just shouldn't be allowed.
Is this something that could be a Needs-Consensus PR?
For the reasons in https://github.com/tc39/ecma262/issues/830#comment-283773904 , I am not convinced this is a problem.
Note that undefined is not alone in that case, as other ”global constants”, namely NaN and Infinity, may be locally rebound as well.
(BTW, I wonder why global.NaN is nonwritable, whilst global.eval is writable.)
(BTW, I wonder why global.NaN is nonwritable, whilst global.eval is writable.)
(Ok, I guess that window.eval = function(x) { throw new EvalError; } /* let’s remove dangerous toys! */ is reasonable, but window.Infinity = 2038; /* it’s distant enough! */ is not.)
It seems like this should be closed. Any thoughts before I do?
Most helpful comment
For the reasons in https://github.com/tc39/ecma262/issues/830#comment-283773904 , I am not convinced this is a problem.