Consider the following code:
var somevar;
function(){
newvar="SomeStr";
}();
I want to understand why does newvar-->"SomeStr"
binding contained into a global namespace? From the spec, §11.13.1 "Simple Assignment (=
)":
The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression is evaluated as follows:
- Let lref be the result of evaluating LeftHandSideExpression.
- Let rref be the result of evaluating AssignmentExpression.
- Let rval be GetValue(rref).
- Throw a SyntaxError exception if the following conditions are all true:
- Type(lref) is Reference is true
- IsStrictReference(lref) is true
- Type(GetBase(lref)) is Environment Record
- GetReferencedName(lref) is either
"eval"
or"arguments"
- Call PutValue(lref, rval).
- Return rval.
newvar
is an identifier. From §10.3.1 "Identifier Resolution":
During execution of ECMAScript code, the syntactic production PrimaryExpression : Identifier is evaluated using the following algorithm:
- Let env be the running execution context’s LexicalEnvironment.
- If the syntactic production that is being evaluated is contained in a strict mode code, then let strict be true, else let strict be false.
- Return the result of calling GetIdentifierReference function passing env, Identifier, and strict as arguments.
GetIdentifierReference (lex, name, strict) is defined in its own section §10.2.2.1, which says:
[…] When called, the following steps are performed:
- If lex is the value null, then
- [a] Return a value of type Reference whose base value is undefined, whose referenced name is name, and whose strict mode flag is strict.
- Let envRec be lex’s environment record.
- Let exists be the result of calling the HasBinding(N) concrete method of envRec passing name as the argument N.
- If exists is
true
, then
- [a] Return a value of type Reference whose base value is envRec, whose referenced name is name, and whose strict mode flag is strict.
- Else
- [a] Let outer be the value of lex’s outer environment reference.
- [b] Return the result of calling GetIdentifierReference passing outer, name, and strict as arguments.
Thus we have that after evaluating newvar
identifier, reference with the name newvar
and base value undefined
will be returned. But when we've tried to invoke PutValue(lref,rval)
during the evaluating of AssignmentExpression
we have
- If Type(V) is not Reference, throw a ReferenceError exception.
- Let base be the result of calling GetBase(V).
If IsUnresolvableReference(V), then
a. If IsStrictReference(V) is true, then
i. Throw ReferenceError exception.
b. Call the [[Put]] internal method of the global object, passing GetReferencedName(V) for the property name, W for the value, and false for the Throw flag.
Else if IsPropertyReference(V), then
a. If HasPrimitiveBase(V) is false, then let put be the [[Put]] internal method of base, otherwise let put be the special [[Put]] internal method defined below.
b. Call the put internal method using base as its this value, and passing GetReferencedName(V) for the property name, W for the value, and IsStrictReference(V) for the Throw flag.
Else base must be a reference whose base is an environment record. So, a. Call the SetMutableBinding (10.2.1) concrete method of base, passing GetReferencedName(V), W, and IsStrictReference(V) as arguments.
- Return.
Thus SetMutableBinding
will call. But base is undefined
and TypeError must be raised. Instead the newvar--->"SomeStr"
binding will be added to a global namespace. Please explain me why?