问题
So, as you may know, the strict mode of JavaScript adds restrictions on the identifiers eval
, and arguments
, effectively making them reserved words, with two exceptions:
- they can still be uses as expressions, i.e. in places where an expression is expected (with a couple of exceptions, though),
- they can still be used as label names, and in
break
/continue
statements to reference labels.
Now, I understand the first bullet. If, for instance, the identifier eval
wasn't allowed as an expression (and true reserved words aren't), we wouldn't be able to invoke the eval
function at all (since eval(str)
is an expression). Same goes for arguments
- we need to be able to use it as an expression in order to be able to access its elements (e.g. arguments[0]
).
This rule has a three exceptions, though. eval
/arguments
may not appear (1) as left-hand side expressions in assignments (e.g. eval = true;
), (2) as operands of ++
/--
(e.g. eval++
), (3) as operands of delete
(e.g. delete eval
). Those are the only exceptions though, and in all other expression-contexts, they are valid.
What I don't understand is the second bullet. Why can they be still used as label names? For instance, this code is valid even in strict mode:
eval: for ( var i = 0; i < 10; i++ ) {
arguments: for ( var j = 0; j < 10; j++ ) {
if ( i < j ) continue eval;
console.log( i - j );
}
}
Notice how continue eval;
references the eval
label, and has nothing to do with the actual eval
function.
Also, notice how true reserved words cannot be used as label names. From my understanding, the intend of strict mode was to make the names eval
, and arguments
as reserved-word-like as possible. Then why keep them as valid label names?
回答1:
I don't know why, but I can hazard a pretty good guess.
The reason eval
and arguments
are restricted for variable names (and, for that matter, why with
is forbidden) is that they affect where variable names bind (i.e. to a local variable, a variable in an enclosing scope, or to a property on the global object if one exists). Without those restrictions, some names are unbound until runtime, with all the hazards that implies.
Label names occupy a different naming space from variable names, property names, and so on. There's never ambiguity about the target of a break
/continue
, because labels are statically assigned and label references are statically resolved. (Yes, eval
code can include labels. But existing jumps can't target those labels, nor can jumps in eval
code target pre-existing labels, because label resolution occurs at compile time, and it is scoped to a Program, to use the ECMAScript terminal's name. A script that contains an eval
call is a Program, and the code executed by the eval
call is a Program, but the two are entirely separate for label-targeting purposes.)
The reason to forbid eval
and arguments
for variable names simply doesn't apply to labels. Therefore, labels can still be named eval
or arguments
. It would be stupid to name a label that way, true. And if someone were designing ECMAScript/JavaScript again, they'd be keywords, and not usable as label names. But there's no gain to be had from forbidding them as label names, and at least a small compatibility argument for not forbidding them, so they were not forbidden.
来源:https://stackoverflow.com/questions/12557574/why-doesnt-strict-mode-restrict-the-identifiers-eval-and-arguments-from-ap