VariableStatement :
var VariableDeclaration ;
VariableDeclarationList :
VariableDeclaration
VariableDeclarationList , VariableDeclaration
Missing NoIn statement?
VariableDeclarationListNoIn :
VariableDeclarationNoIn
VariableDeclarationListNoIn , VariableDeclarationNoIn
VariableDeclaration :
Identifier Initialiser(opt)
VariableDeclarationNoIn :
Identifier InitialiserNoIn(opt)
Initialiser :
= AssignmentExpression
InitialiserNoIn :
= AssignmentExpressionNoIn
The var statement declares variables as defined in 10.5 and initialises them to undefined when created. The initialiser is assigned at the time of execution of the statement, not when the variable is declared. So when a var statement is executed only initialisers actually do something, since all the variables will have been created at that point.
function evaluate(var VariableDeclarationList ;) {
evaluate(VariableDeclarationList);
return Completion('normal', undefined, undefined);
}
function evaluate(VariableDeclaration) {
return evaluate(VariableDeclaration);
}
function evaluate(VariableDeclarationList , VariableDeclaration) {
evaluate(VariableDeclarationList);
evaluate(VariableDeclaration);
// No return here??
}
This case proves why evaluate must have a Production and Matches parameter... This definition would clash with 11.1.2.
function evaluate(Identifier) {
// "return a String value containing the same sequence of characters as in the Identifier"
return Identifier; // todo: create interface for that :)
// return value is used in 12.6.4, for .. in
}
function evaluate(Identifier) {
var lhs = evaluate(Identifier); // 11.1.2, returns Reference of bound Identifier
var rhs = evaluate(Initialiser);
var value = GetValue(rhs);
PutValue(lhs, value);
// "return a String value containing the same sequence of characters as in the Identifier"
return Identifier; // todo: create interface for that :)
// return value is used in 12.6.4, for .. in
}
The specification notes that if a VariableDeclaration is nested within a WithStatement and the Identifier in the VariableDeclaration is the same as a prototype name of the binding object of the WithStatement's object environment record, then step 4 (call to PutValue) will assign value to the property instead of to the VariableEnvironment binding of the Identifier.
In other words, if
- you declare a variable, and
- use an initialiser, and
- are in a with block, and
- the variable name also exists as a property of the prototype of the with's object, then
the property of the prototype is set to the initialiser instead. (Why? Due to 11.1.2? Due to GetValue? Due to PutValue? Special condition? Need to find out. And is the property of the prototype changed? Or is the property of the object set to the initialiser?)
function evaluate(AssignmentExpression) {
return evaluate(AssignmentExpression);
}
The NoIn versions behave exactly the same.