enum is a new LexicalDeclaration binding form, similar to let or const.
typeof enum is object; similar to Array, it's just a special Object (more below)
EnumDeclaration with no BindingIdentifier creates const bindings corresponding to each EnumEntryName:
enum {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
Is equivalent to:
const SUNDAY = 0;
const MONDAY = 1;
const TUESDAY = 2;
const WEDNESDAY = 3;
const THURSDAY = 4;
const FRIDAY = 5;
const SATURDAY = 6;
EnumDeclaration or EnumExpression with a BindingIdentifier creates:
A proto-less, frozen object;
Creates PropertyName corresponding to each EnumEntryName:
enum DaysOfWeek {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
const DaysOfWeek = enum {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
};
Is approximately* equivalent to:
const DaysOfWeek = Object.freeze(
Object.create(null, {
[Symbol.enumSize]: {
// Specification can define better semantics for deriving
// and storing the size of the enum object (internal slot)
value: 7
},
[Symbol.iterator]: {
* value() {
// Specification can define better semantics for deriving
// and storing keys and values (internal slot)
let keys = Object.keys(DaysOfWeek);
let values = Object.values(DaysOfWeek);
let index = 0;
while (index < keys.length) {
yield [keys[index], values[index]];
index++;
}
}
},
SUNDAY: { value: 0, enumerable: true },
MONDAY: { value: 1, enumerable: true },
TUESDAY: { value: 2, enumerable: true },
WEDNESDAY: { value: 3, enumerable: true },
THURSDAY: { value: 4, enumerable: true },
FRIDAY: { value: 5, enumerable: true },
SATURDAY: { value: 6, enumerable: true },
})
);
for (let [day, value] of DaysOfWeek) { console.log(value, day) }
/*
0 SUNDAY
1 MONDAY
2 TUESDAY
3 WEDNESDAY
4 THURSDAY
5 FRIDAY
6 SATURDAY
*/
EnumDeclaration or EnumExpression will set the value of each entry to an integer, starting at 0 and incrementing by 1 for each entry.
EnumDeclaration may have EnumEntryName inline assignment overrides. If an entry has an inline assignment, the default value is incremented as normal, but not used for that entry.
enum {
FOO,
BAR = _AssignmentExpression_,
BAZ,
}
Is equivalent to:
const FOO = 0;
const BAR = _AssignmentExpression_;
const BAZ = 2;
EnumDeclaration (with BindingIdentifier) or EnumExpression example:
enum Things {
FOO,
BAR = _AssignmentExpression_,
BAZ,
}
const Things = enum {
FOO,
BAR = _AssignmentExpression_,
BAZ,
};
Is approximately equivalent to:
const DaysOfWeek = Object.freeze(
Object.create(null, {
/*
Assume Symbol.enumSize and Symbol.iterator
*/
FOO: { value: 0, enumerable: true },
BAR: { value: _AssignmentExpression_, enumerable: true },
BAZ: { value: 2, enumerable: true },
})
);
Of course, this means that the value of an enum entry can be whatever you want it to be:
// todo
EnumDeclaration may have ComputedPropertyName as EnumEntryName:
enum {
FOO,
["BAR"],
BAZ,
}
Is equivalent to:
const FOO = 0;
const BAR = 1;
const BAZ = 2;
EnumDeclaration (with BindingIdentifier) or EnumExpression example:
enum Things {
FOO,
[Symbol(...)],
BAZ,
}
const Things = enum {
FOO,
[Symbol(...)],
BAZ,
};
Is approximately equivalent to:
const DaysOfWeek = Object.freeze(
Object.create(null, {
/*
Assume Symbol.enumSize and Symbol.iterator
*/
FOO: { value: 0, enumerable: true },
[Symbol(...)]: { value: 1, enumerable: true },
BAZ: { value: 2, enumerable: true },
})
);
EnumDeclaration may not have duplicate EnumEntryName:
These throw exceptions:
enum {
FOO,
FOO
}
enum {
FOO,
["BAR"],
BAR,
}
EnumDeclaration with an EnumValueMap to populate the values of the Enum:
function EnumValueMap(key, index) {
return 1 << index;
}
enum via EnumValueMap {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
}
// Is equivalent to:
const SUNDAY = EnumValueMap(SV(SUNDAY), 0); // 0b00000001
const MONDAY = EnumValueMap(SV(MONDAY), 1); // 0b00000010
const TUESDAY = EnumValueMap(SV(TUESDAY), 2); // 0b00000100
const WEDNESDAY = EnumValueMap(SV(WEDNESDAY), 3);// 0b00001000
const THURSDAY = EnumValueMap(SV(THURSDAY), 4); // 0b00010000
const FRIDAY = EnumValueMap(SV(FRIDAY), 5); // 0b00100000
const SATURDAY = EnumValueMap(SV(SATURDAY), 6); // 0b01000000
And the BindingIdentifier example:
function EnumValueMap(key, index) {
return 1 << index;
}
enum DaysOfWeekAsBits via EnumValueMap {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
}
Is approximately equivalent to:
const DaysOfWeekAsBits = Object.freeze(
Object.create(null, {
[Symbol.enumSize]: {
// Specification can define better semantics for deriving
// and storing the size of the enum object (internal slot)
value: 7
},
[Symbol.iterator]: {
* value() {
// Specification can define better semantics for deriving
// and storing keys and values (internal slot)
let keys = Object.keys(DaysOfWeekAsBits);
let values = Object.values(DaysOfWeekAsBits);
let index = 0;
while (index < keys.length) {
yield [keys[index], values[index]];
index++;
}
}
},
SUNDAY: { value: EnumValueMap(SV(SUNDAY), 0), enumerable: true },
MONDAY: { value: EnumValueMap(SV(MONDAY), 1), enumerable: true },
TUESDAY: { value: EnumValueMap(SV(TUESDAY), 2), enumerable: true },
WEDNESDAY: { value: EnumValueMap(SV(WEDNESDAY), 3), enumerable: true },
THURSDAY: { value: EnumValueMap(SV(THURSDAY), 4), enumerable: true },
FRIDAY: { value: EnumValueMap(SV(FRIDAY), 5), enumerable: true },
SATURDAY: { value: EnumValueMap(SV(SATURDAY), 6), enumerable: true },
})
);
for (let [day, value] of DaysOfWeekAsBits) { console.log(value, day) }
/*
0b00000001 SUNDAY
0b00000010 MONDAY
0b00000100 TUESDAY
0b00001000 WEDNESDAY
0b00010000 THURSDAY
0b00100000 FRIDAY
0b01000000 SATURDAY
*/
WebIDL could specify its enum as using a default EnumValueMap; ie. https://heycam.github.io/webidl/#idl-enumeration might update its definition:
An enumeration is a definition (matching Enum) used to declare a type whose valid values are a set of predefined strings.
To:
An enumeration is a definition (matching Enum) used to declare a type whose valid values are a set of predefined strings.
An ECMAScript implementation of WebIDL enum would use a String EnumValueMap.
enum RTCPeerConnectionState via String {
new,
connecting,
connected,
disconnected,
failed,
closed,
};
Is approximately equivalent to:
const RTCPeerConnectionState =Object.freeze(
Object.create(null, {
[Symbol.enumSize]: {
// Specification can define better semantics for deriving
// and storing the size of the enum object (internal slot)
value: 6
},
[Symbol.iterator]: {
* value() {
// Specification can define better semantics for deriving
// and storing keys and values (internal slot)
let keys = Object.keys(RTCPeerConnectionState);
let values = Object.values(RTCPeerConnectionState);
let index = 0;
while (index < keys.length) {
yield [keys[index], values[index]];
index++;
}
}
},
// Note that this case illustrates that it's ok for the
// for the second argument to be ignored.
new: { value: String(SV(new)), enumerable: true },
connecting: { value: String(SV(connecting)), enumerable: true },
connected: { value: String(SV(connected)), enumerable: true },
disconnected: { value: String(SV(disconnected)), enumerable: true },
failed: { value: String(SV(failed)), enumerable: true },
closed: { value: String(SV(closed)), enumerable: true },
})
);
* Approximately means that it doesn't fully represent all of the semantics.
11 commits
enum is a new LexicalDeclaration binding form, similar to let or const.
typeof enum is object; similar to Array, it's just a special Object (more below)
EnumDeclaration with no BindingIdentifier creates const bindings corresponding to each EnumEntryName:
enum {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
Is equivalent to:
const SUNDAY = 0;
const MONDAY = 1;
const TUESDAY = 2;
const WEDNESDAY = 3;
const THURSDAY = 4;
const FRIDAY = 5;
const SATURDAY = 6;
EnumDeclaration or EnumExpression with a BindingIdentifier creates:
A proto-less, frozen object;
Creates PropertyName corresponding to each EnumEntryName:
enum DaysOfWeek {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
const DaysOfWeek = enum {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
};
Is approximately* equivalent to:
const DaysOfWeek = Object.freeze(
Object.create(null, {
[Symbol.enumSize]: {
// Specification can define better semantics for deriving
// and storing the size of the enum object (internal slot)
value: 7
},
[Symbol.iterator]: {
* value() {
// Specification can define better semantics for deriving
// and storing keys and values (internal slot)
let keys = Object.keys(DaysOfWeek);
let values = Object.values(DaysOfWeek);
let index = 0;
while (index < keys.length) {
yield [keys[index], values[index]];
index++;
}
}
},
SUNDAY: { value: 0, enumerable: true },
MONDAY: { value: 1, enumerable: true },
TUESDAY: { value: 2, enumerable: true },
WEDNESDAY: { value: 3, enumerable: true },
THURSDAY: { value: 4, enumerable: true },
FRIDAY: { value: 5, enumerable: true },
SATURDAY: { value: 6, enumerable: true },
})
);
for (let [day, value] of DaysOfWeek) { console.log(value, day) }
/*
0 SUNDAY
1 MONDAY
2 TUESDAY
3 WEDNESDAY
4 THURSDAY
5 FRIDAY
6 SATURDAY
*/
EnumDeclaration or EnumExpression will set the value of each entry to an integer, starting at 0 and incrementing by 1 for each entry.
EnumDeclaration may have EnumEntryName inline assignment overrides. If an entry has an inline assignment, the default value is incremented as normal, but not used for that entry.
enum {
FOO,
BAR = _AssignmentExpression_,
BAZ,
}
Is equivalent to:
const FOO = 0;
const BAR = _AssignmentExpression_;
const BAZ = 2;
EnumDeclaration (with BindingIdentifier) or EnumExpression example:
enum Things {
FOO,
BAR = _AssignmentExpression_,
BAZ,
}
const Things = enum {
FOO,
BAR = _AssignmentExpression_,
BAZ,
};
Is approximately equivalent to:
const DaysOfWeek = Object.freeze(
Object.create(null, {
/*
Assume Symbol.enumSize and Symbol.iterator
*/
FOO: { value: 0, enumerable: true },
BAR: { value: _AssignmentExpression_, enumerable: true },
BAZ: { value: 2, enumerable: true },
})
);
Of course, this means that the value of an enum entry can be whatever you want it to be:
// todo
EnumDeclaration may have ComputedPropertyName as EnumEntryName:
enum {
FOO,
["BAR"],
BAZ,
}
Is equivalent to:
const FOO = 0;
const BAR = 1;
const BAZ = 2;
EnumDeclaration (with BindingIdentifier) or EnumExpression example:
enum Things {
FOO,
[Symbol(...)],
BAZ,
}
const Things = enum {
FOO,
[Symbol(...)],
BAZ,
};
Is approximately equivalent to:
const DaysOfWeek = Object.freeze(
Object.create(null, {
/*
Assume Symbol.enumSize and Symbol.iterator
*/
FOO: { value: 0, enumerable: true },
[Symbol(...)]: { value: 1, enumerable: true },
BAZ: { value: 2, enumerable: true },
})
);
EnumDeclaration may not have duplicate EnumEntryName:
These throw exceptions:
enum {
FOO,
FOO
}
enum {
FOO,
["BAR"],
BAR,
}
EnumDeclaration with an EnumValueMap to populate the values of the Enum:
function EnumValueMap(key, index) {
return 1 << index;
}
enum via EnumValueMap {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
}
// Is equivalent to:
const SUNDAY = EnumValueMap(SV(SUNDAY), 0); // 0b00000001
const MONDAY = EnumValueMap(SV(MONDAY), 1); // 0b00000010
const TUESDAY = EnumValueMap(SV(TUESDAY), 2); // 0b00000100
const WEDNESDAY = EnumValueMap(SV(WEDNESDAY), 3);// 0b00001000
const THURSDAY = EnumValueMap(SV(THURSDAY), 4); // 0b00010000
const FRIDAY = EnumValueMap(SV(FRIDAY), 5); // 0b00100000
const SATURDAY = EnumValueMap(SV(SATURDAY), 6); // 0b01000000
And the BindingIdentifier example:
function EnumValueMap(key, index) {
return 1 << index;
}
enum DaysOfWeekAsBits via EnumValueMap {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
}
Is approximately equivalent to:
const DaysOfWeekAsBits = Object.freeze(
Object.create(null, {
[Symbol.enumSize]: {
// Specification can define better semantics for deriving
// and storing the size of the enum object (internal slot)
value: 7
},
[Symbol.iterator]: {
* value() {
// Specification can define better semantics for deriving
// and storing keys and values (internal slot)
let keys = Object.keys(DaysOfWeekAsBits);
let values = Object.values(DaysOfWeekAsBits);
let index = 0;
while (index < keys.length) {
yield [keys[index], values[index]];
index++;
}
}
},
SUNDAY: { value: EnumValueMap(SV(SUNDAY), 0), enumerable: true },
MONDAY: { value: EnumValueMap(SV(MONDAY), 1), enumerable: true },
TUESDAY: { value: EnumValueMap(SV(TUESDAY), 2), enumerable: true },
WEDNESDAY: { value: EnumValueMap(SV(WEDNESDAY), 3), enumerable: true },
THURSDAY: { value: EnumValueMap(SV(THURSDAY), 4), enumerable: true },
FRIDAY: { value: EnumValueMap(SV(FRIDAY), 5), enumerable: true },
SATURDAY: { value: EnumValueMap(SV(SATURDAY), 6), enumerable: true },
})
);
for (let [day, value] of DaysOfWeekAsBits) { console.log(value, day) }
/*
0b00000001 SUNDAY
0b00000010 MONDAY
0b00000100 TUESDAY
0b00001000 WEDNESDAY
0b00010000 THURSDAY
0b00100000 FRIDAY
0b01000000 SATURDAY
*/
WebIDL could specify its enum as using a default EnumValueMap; ie. https://heycam.github.io/webidl/#idl-enumeration might update its definition:
An enumeration is a definition (matching Enum) used to declare a type whose valid values are a set of predefined strings.
To:
An enumeration is a definition (matching Enum) used to declare a type whose valid values are a set of predefined strings.
An ECMAScript implementation of WebIDL enum would use a String EnumValueMap.
enum RTCPeerConnectionState via String {
new,
connecting,
connected,
disconnected,
failed,
closed,
};
Is approximately equivalent to:
const RTCPeerConnectionState =Object.freeze(
Object.create(null, {
[Symbol.enumSize]: {
// Specification can define better semantics for deriving
// and storing the size of the enum object (internal slot)
value: 6
},
[Symbol.iterator]: {
* value() {
// Specification can define better semantics for deriving
// and storing keys and values (internal slot)
let keys = Object.keys(RTCPeerConnectionState);
let values = Object.values(RTCPeerConnectionState);
let index = 0;
while (index < keys.length) {
yield [keys[index], values[index]];
index++;
}
}
},
// Note that this case illustrates that it's ok for the
// for the second argument to be ignored.
new: { value: String(SV(new)), enumerable: true },
connecting: { value: String(SV(connecting)), enumerable: true },
connected: { value: String(SV(connected)), enumerable: true },
disconnected: { value: String(SV(disconnected)), enumerable: true },
failed: { value: String(SV(failed)), enumerable: true },
closed: { value: String(SV(closed)), enumerable: true },
})
);
* Approximately means that it doesn't fully represent all of the semantics.
11 commits