Abstract
This is a brief review of the ECMAScript specifications 5 and 5.1, the latter published in 2011.
ECMAScript: Why ES4 was Never Published?
Once there were ES1, ES2, ES3 and the following ES in the series, the ES4, was greatly expected as well. ES4, however, never arrived; instead, a mysterious ES 5.1 finally came from the shadows and it brought some harmony to the world. That atempt of tale actually happened in the history of JavaScript. One of my tags in this digital garden is about JavaScript, and I have been doing some research about its history and its quirks. One of the things I have been writing in some seeds is about the ECMAScript specifications and everyhing was going well, but suddenlty a disruption appeared. I had a big suprise when I found that there were no ES4 as I might be expecting following the history of specifications, but the anomaly was there. So, a big curiosity grew in my mind, and this seed is the result of it. I wanted to understand this chapter of the history of ECMAScript.
The obvious question is: why? What happened at that time such that there were not ES4? The long story short is this: there were no concensus about the next step in the evolution of JavaScript. With no concensus, a new version of the standard cannot be released and the language’s evolution was stopped. It seems to me that it is worthy to try to answer why that happened, so, I am going to review some details of the tale.

This chapter of the evolution of JavaScript was about differente visions for the language. On one hand, companies like Adobe, for example, were interested in a big leap in the advance of ECMAScript mostly because they had its own advanced version of JavaScript called ActionScript, and integrating their own advances in the main branch of the standard of ECMAScript could be great for the language. Their vision of JavaScript was with new features that would convert that small scripting language for the browser in a full fledge programming language for large scale developments on its own. Microsoft was interested in the integration of JScript .NET into the main branch of JavaScript as well, and the implementation of . ActionScript was already using those big features, especially in their famous flgaship producto: Flash. On the other hand, the general vision of the evolution of JavaScript was backwards compatibility, which means that any intepreter must assure that an earlier version of the language must run in an intepreter capable of running the lastest one. Thus, the lack of concensus started and the eventual paralysis of the TC39 committee.

Photo by Tim Mossholder on Unsplash
With the initiative of Adobe, and its interest of incorporate ActionScript into ECMAScript, the TC39 retook the process of standardization and an ES4 draft started to take form, but again, other players in the committee did not agree on the drafted proposal. Breaking the Web was not an alternative, breaking the Web spending money building new intepreters was neither, and breaking the Web losing makert dominance was not, of course, another option. So, again there was no concensus and either by technical, strategic or market reasons, the ES4 stalled.
Then, two team were created: one for continuing working on ES4, the other focused on finding a subset of ES4 that were useful and still easy to implement. That useful subset of ECMAScript was named ES 3.1, and it did considerable progress while the ES4 team definitively not. In addition, Adobe was planning to withdraw from the ES4 development as well, and a point of no agreement started to take place again.
In 2008, Oslo was the city choosen to be the witness a a hard decision: ES4 was officially dead. However, the hope for the evolution of JavaScript did not die, and the meeting paved the way to Harmony. What did it mean? Because ES4 was dead, the effort was focused on the advances made on ES 3.1; there was an agreement around of the idea that some ES4 were not suitable for the Web. As a result, the ECMAScript specification 3.1 was named ES5, and it was released in 2009, almost a year after the dead of ES4 was the necessary sacrifice to get the right path of enlightment again.

Photo by Diana Polekhina on Unsplash
ES5 and ES5.1
Since the Oslo meeting, the word Harmony took a new meaning. Onwards, the development of ECMAScript should avoid the traps of ES4. It would allow the possibility of adding complex features to the language without breaking anything. After the struggle, then, JavaScript preserved its nature: a scripting language designed to be run withing a host environment, used to manipulate or automate the facilities of such environment or any other existing system.
The ES5 was released and was approved as the new ECMAScript standard. There were, however, minor corrections to ES5 and there were incorporated in a new document called ES 5.1 that was adpoten in June 2011. From the technical perspective, ES5 ’[…] codified de facto interpretations of the language specification that have become common among browser implementations and added support for new features that had emerged since the publication of the third edition. Such features include accessor properties, reflective creation and inspection of objects, program control of property attributes, additional array manipulation functions, support for the JSON object encoding format, and a strict mode that provides enhanced error checking and program security.‘
The JSON Object
One new feature was the support for the JSON object encoding. JSON has been a way to enconde information both human and machine readable, and it is the De Facto modern encoding for the Web. It is natural that such encoding should be included in one of the open standard languages of the Web. With this support, converting values from JSON to Javascript objects and vice versa is built-in by default. The JSON object, unlike the other JavaScript objects is not a contructor Function, but every property or method is static. Converting from JavaScript object to JSON is called serialization. The method JSON.stringify() returns a string corrsponding the the JSON value, and the process of converting a string representation of a JSON value is called parsing. With the JSON.parse() method a string JSON value is transformed into a JavaScript object.
// From JS object to JSON string.
const jsonString = JSON.stringify({ hello: 'world' });
console.log(jsonString); // '{"hello":"WORLD"}'
// From string to JS Object.
const jsObject = JSON.parse('{"hello":"WORLD"}');
console.log(jsObject) // { hello: "WORLD" }
The ‘strict mode’ vs the ‘sloppy mode’
Although the nature of JavaScript did not changed, however a new variant of the language was incorporated almost in a stealth mode. This new variant of the language is an optional feature, and it is a more restricted version of it. According to the MDN, this new variant of the language is not just a subset of JavaScript, but ‘it intentionally has different semantics for normal code’. In simple terms, different semantics means a different behavior for the same syntax. Thus, instead of breaking the Web, they created two semantics for the same language: one strict and the other does not. But, what does it mean to be strict in JavaScript terms? Here are the main changes of the semantics of the language in this new strict mode according to the MDN:
- Eliminates some JavaScript silent errors by changing them to throw errors.
- Fixes mistakes that make it difficult for JavaScript engines to perform optimizations: strict mode code can sometimes be made to run faster than identical code that’s not strict mode.
- Prohibits some syntax likely to be defined in future versions of ECMAScript.
In a word, developers may know for sure when they broke things, JavaScript may run faster and future members of the TC39 may not be allowed to go the wrong way.
The strict mode applies to entire scripts or to individual functions. It does not apply for block statements enclosed in curly brackets . For scripts, invoking the strict mode for the entire script is made by adding the statement “use strict”; or ‘use strict’; before any other statements. For example:
// Invoking the scrict semantics for a whole script.
"use strict";
// Invoking the scrict semantics for a whole script.
'use strict';
For functions, the scrict mode is invoked putting the same exact statement at the beginning of the function code, before any other code. If a function is defined inside a strict mode function body, then that function is in strict mode as well. Here is the exampled taken from the MDN documentation:
function myStrictFunction() {
// Function-level strict mode syntax
"use strict";
function nested() {
return "And so am I!";
}
return `Hi! I'm a strict mode function! ${nested()}`;
}
function myNotStrictFunction() {
return "I'm not strict.";
}
There is a catch, however, when applying the strict mode to functions. It can be applied to functions with simple parameters, otherwise it is a syntax error. For example:
function sum(a = 1, b = 2) {
// SyntaxError: "use strict" not allowed in function with default parameter
"use strict";
return a + b;
}
Accessor Properties
In JavaScript, an object is defined as a collection of properties. Each property is either a named data property, a named accessor property or an internal property. What are those type of properties? What is their functionalty? Why we do need them? Let’s try to going deeper on those questions.
First, according to the ECMAScript specification 5.1, the three kind of properties an object can have are the following:
- A named data property associates a name with a value and a set of boolean attributes.
- A named accessor property associates a name with one or two accessor functions, and a set of boolean values. The accessor functions are used to store or retrieve an ECMAScript language value that is associated with the property.
- An internal property has no name and it is not directly accesible via ECMAScript language itself. They exists for specification purposes only.
Each type of property has its own attributes. Attributes can be accessed directly only but the JavaScript engine or interpreter, but they can be read or changed through the Object API. So, for example, data properties, the first type in the list, associates key and value pairs. Their attributes are: writable, configurable, enumerable and value as we will see in detail in a table below. On the other hand, an accessor property, the second type in the list, associates a key with two accessor functions get and set.
According to the ECMAScript specification 5.1, there are two kinds of access for named properties: get and put , corresponding to retrieval and assignment respectively. Those are the very basic operations defined on object properties in any object. In the next example, we use dot notation to access the property’s associated value and use the assignment operator to change the property’s associated value:
// Here we are doing a basic literal object creation with some named properties.
var data = {
id: 1200,
espec: true,
description: "Named and internal javascript properties"
}
// Here we are retrieving the associated value of some property.
consle.log(data.description) // We get the string value associated with the named property description
// Next we are doing a put operation on some property.
data.id = 2400
Property attributes or simply attributes are used to define the state of named properties. In the ECMAScript 5.1, a named data property associates a name with the following attributes:
Attribute Name | Value Domain | Description |
---|---|---|
[[Value]] | Any ECMAScript value | The value retrieved by reading the property |
[[Writable]] | Boolean | If false, attempts by ECMAScript code to change the property’s [[Value]] attribute using [[Put]] will not succeed. |
[[Enumerable]] | Boolean | If true, the property will be enumerated by a for-in enumeration. Otherwise, the property is said to be non-enumerable. |
[[Configurable]] | Boolean | If false, attempts to delete the property, change the property to be an accessor property, or change its attributes (other than [[Value]]) will fail. |
Those property attributes or property descriptors are just plain JavaScript objects and they are accesible via Object API. In this case, the static method Object.getOwnPropertyDescriptor returns an object with the property attributes for a given data property. For example, the following object has three properties, and the variable namedDataProperty is the object describing the current attributes or accessor properties of the named data property “id”.
var data = {
id: 345345,
prop: true,
description: "A JavaScript String Description"
}
var namedDataProperty = Object.getOwnPropertyDescriptor(data, "id");
console.log(namedDataProperty);
// This will show in the console the attributes of the property id:
{
configurable: true
enumerable: true
value: 345345
writable: true
}
The second type of properties are accessor properties and as already said, they associates a key with two accesor functions get and set. The specification has the following table showing attributes for named accessor properties.
Attribute Name | Value Domain | Description |
---|---|---|
[[Get]] | Object or Undefined | If the value is an Object it must be a function Object. The function’s [[Call]] internal method is called with an empty arguments list to return the property value each time a get access of the property is performed. |
[[Set]] | Object or Undefined | If the value is an Object it must be a function Object. The function’s [[Call]] internal method is called with an arguments list containing the assigned value as its sole argument each time a set access of the property is performed. The effect of a property’s [[Set]] internal method may, but is not required to, have an effect on the value returned by subsequent calls to the property’s [[Get]] internal method. |
[[Enumerable]] | Boolean | If true, the property is to be enumerated by a for-in enumeration Otherwise, the property is said to be non-enumerable. |
[[Configurable]] | Boolean | If false, attempts to delete the property, change the property to be a data property, or change its attributes will fail. |
The last set of properties are called internal properties. They are not part of the ECMAScript language itself, but used by specification purposes.
⚠️ This is a work in progress ⚠️
Now let’s play a little bit with those property descriptors. For example, if we change the writable accessor property of the “id” property from true to false, after that we won’t be able to set a new value for it. It has become a kind of read-only-constant-value-property. To set a property descriptor we can use the Object API again, but this time with the static method defineProperty. That method receives an object, a property name and an object setting the new property descriptors as argument, and returns the object passed as first argument with its new accessor properties changed accordingly. So, following the previous example we have:
var data = {
id: 345345,
prop: true,
description: "A JavaScript String Description"
}
var namedDataProperty = Object.getOwnPropertyDescriptor(data, "id");
console.log(namedDataProperty);
// Here we change the writable property to false
Object.defineProperty(data, "id", {
writable: false
});
// This attempt to change [[Value]] will fail.
data.id = 42
console.log(data);
// Thus, The following log will be similar to:
{
description: "A JavaScript String Description"
id: 345345
prop: true
}
If we iterate over the object’s properties using a for-in loop and each time we log the property, we could see a log with “id”, “prop” and “description” printed in the console. However, changing the [[Enumerable]] accessor property of “prop” to false, for example, the next time we iterate over the object, the for-in loop won’t access the property anymore. Nonetheless, such property is still accesible via normal property access using dot or bracket notation, and it is still writable.
var data = {
id: 345345,
prop: true,
description: "A JavaScript String Description"
}
// This will log id, prop and description.
for (const key in data) {
console.log(key);
}
// Here we change the value of the accessor [[Enumerable]] from true to false.
Object.defineProperty(data, "prop", {
enumerable: false
});
// This will log only id and description.
for (const key in data) {
console.log(key);
}
⚠️ This is a work in progress ⚠️
Linked Seeds
External Links
- ECMAScript 5.1 Specification - PDF
- The Real Story Behind ES4
- ES4 the Missing Version
- Online Archives of Versions of ECMAScript Specifications
- A Brief History of Javascript
- A Short History of JavaScript
- Wikipedia Entry about ActionScript
- JavaScript 2.0 1999 Draft for ES4
- Introducing JScript .NET
- JSON Specification
- JSON Object - MDN
- The Strict Mode - MDN
- Web Version of Spec 5.1
- JavaScript Data Types and Data Structures