ES1 Specification

Abstract

A quick review of the first ECMAScript Specification published in 1997.


From JavaScript, JScript to ECMAScript



The ECMA (European Computer Manufacturers Association) standard defines the current specification of ECMAScript a.k.a. JavaScript. Such a specification was necessary because there were on the market two version of the language: JavaScript and JScript. There were two versions of the language available at the same time because there were two web browsers competing for dominance in the browser market. As a result, the user and developer experience were affected because there was not a consistent experience and language semantics across the browsers. Designing and developing fro the Web had a big risk: some scripting code that worked well in one browser, maybe does not in the other.



The war was so evident, that even the specificaition described that moment of the history of JavaScript with this words: ‘This ECMA Standard is based on several originating technologies, the most well known being JavaScript™ (Netscape Communications) and JScript™ (Microsoft Corporation). The development of this Standard has started in November 1996’.



JavaScript was a great innovation and a key differentiator of the browser technology because it brought interactivity to the Web. Rapidly, the Netscape’s competition developed its own scripting language for the Web; Suddenly, the Web had forked into two ways of navigation, two different visions of it as well. In the middle of the struggle, Netscape opted for give to its scripting language an open nature through a thrid party organization in ordder to do not stop innovation and creativity on the Web, as well as allowing fair competition in the market. In that process, ECMA registered the name ECMAScript as trademark; since then, it is the official name for the scripting language that brought interactivity to the Web.



A picture of the JavaScript logo.


The First ECMAScript Standard: ES1 1997



The official document where ECMAScript is specified is the ECMA 262. The first version was published in June 1997. In the first edition of the standard, the language is defined as ‘A general purpose, cross-platform programming language’. The first specification has 110 pages and define notational conventions, data types, execution contexts, expressions, statements and the ECMAScript native objects.



With the first standard, the concept of conformance was defined: ‘A conforming implementation of ECMAScript must provide and support all the types, values, objects, properties, functions, and program syntax described in this specification’. It meant that there is a base line of the language that should be common to any implementation of the language. With that base language, it was possible for designers and developers be sure that their developments will work on any browser.



What if some browser developer would like to go beyond the first specification? It was permitted by the specification itself: ‘A conforming implementation of ECMAScript is permitted to provide additional types, values, objects, properties, and functions beyond those described in this specificaition. In particular, a conforming implementation of ECMAScript is permitted to provide properties not described in this specification, and values for those properties, for objects that are described in this specification.’ Thus, the specification from the beginning was open to innovation and evolution.



The Nature of ECMAScript



In the first page of the specificaition, JavaScript was defined as an object-oriented language intended to be executed within a host environment. Its main goal was performing computations and manipulating computational objects within such host environment. As such, JavaScript did not expect input data, and there were not computational results neither. Its nature was to be embedded in another program, the host program, and commuticate to the computational objects provided by the host through APIs.



JavaScript was also defined in 1997 as a scripting language. According to the specificaition: ‘A scripting language is a programming language that is used to manipulate, customize, and automate the facilities of an existing system.’ Thus, it was not intended as self-sufficient language since the beginning of its history, but to be embedded in other systems. A scripting language expose to professional and non-professional developers the existing functionality of the system in order to control it programmatically in an easy and lightweight manner. Althoug JavaScript was born as a Web Scripting Language, in the first specificaition it was defined with more generality just as scripting language to serve in any host environment, and the specificaition was writen with that idea.



'A scripting language is a programming language that is used to manipulate, customize, and automate the facilities of an existing system.'



Client and Server Scripting



From the beginning, JavaScript was thought as the Web scripting language. It means that it was a language intended to performs computations in the client and server host environments. First, the client side of the Web is the user agent or simply the Browser. As such, the Web Browser provides a host environment for any scripting language for client-side computations. However, due to the tied history of JavaScript with Netscape Navigation Browser, it became The scripting language of the Web.



As a web scripting language, JavaScript has the ability to deal with objects that represents windows, menus, pop-ups, text-areas, cookies and other client-side objects. Further, the host environment also provides means to attach scripting code to events. As a result, the scripting code is reactive to user interaction and there is no need for a main program. The scripting code should be shipped in the HTML itself, so when the Browser starts to parse the HMTL, it starts the parsing and execution of JavaScript scripting code. That is other way to defina a scripting language, it is always ready to be executed in any context. From the server-side of the Web, the host also provides computational objects to be processed by JavaScript like requests, responses, files and son on. Thus, the idea of a common interface for Web-based applications was already in 1997.



A representing the client-server web achitecture.


Language Overview



The following is a brief overview of JavaScript as defined in 1997. According to the specificaition, ECMAScript is object-based because ‘basic language and host facilities are provided by objects, and an ECMAScript program is a cluster of communicating objects.’ It sounds great, but what is an object?



An ECMAScript object is an unordered collection of properties each with 0 or more attributes which determine how each property can be used. As an example: when the attribute ReadOnly is set true for some property, then any attempt to change its state has no effect. Properties are containers for other objects, primitive values or methods. A primitive value is a member of one of the following built-in data types: Undefined, Null, Boolean, Number and String. For example: ‘undefined’ value is the only one value of ‘Undefined’ type; ‘null’ value of the ‘Null’ type; true and false values of the Boolean type and so on. Objects are members of the built-in type Object, and a method is a function associated with an object via a property.



Other built-in objects were also defined in 1997: Global, Object, Function, Array, String, Boolean, Number, Math and Date. All this features surprised me because I thought that ECMAScript was a more primitive language, and now I realize that from the beginning JavaScript had its characteristical flavor.



A symbol of web programming.


More about Objects



What is an Object? That is almost an existential question which is well responded in the first specificaition. A JavaScript object does not contain proper classes such as those in C++ or Java. However, JavaScript objects support constructors. A constructor creates an object by executing code that allocates storage for the object and initializes all or part of them by assigning inital values to their properties.



Constructors are functions, so they are objects too. Each constructor has a Prototype property which is used to implement prototype-based inheritance and shared properties. Objects are created by the new expression. For example, the next expression produces a new String, Boolean and Number objects:




  new String("This is not a String");
  new Boolean(100);
  new Number(500);



A Function object was usueful to create ‘anonymous functions’ dynamically. Anonymous functions are pieces of executable code that are not bound to a name. For example, the first line of the following code creates a Function object, and the second line creates another Function object with parameter named ‘a’ and ‘b’, and the last string is the body of the function itself:




  var u = new Function();
  u()       // returns undefined
  var f = new Function('a', 'b', 'return a + b;');
  f(10, 20) // returns 30



Because each constructor has a prototype property, it was possible to implement a Prototype-based inheritance. It means that every constructor has an associated prototype, and every object created by that constructor has an implicit reference to the prototype associated with its construcctor. Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; that chain of prototypes is called the ‘prototype chain’.



It means that when a reference is made to a property in an object, that reference is to the property of that name in the first object in the prototype chain that contains a property of that name. In other words, to look up for a property in the prototype chain, first is looked up in the object, if it is not there, a new look up must be done in its prototype, and so on; the search stops when the property in found or returns ‘undefined’ otherwise.



All objects that do not directly contain a particular property that their prototype contains share that property and its value. The following diagram is an excerpt from the official ES1 specificaition and it is intended to illustrate the discussion:



A diagram explaining the JavaScript prototype chain.


A Brief Review of some Aspects of the Language



By 1997, JavaScript started its journey into the specificaition process, and the preservation of the its spirit was critial. As a host language, JavaScript had its own native or built-in objects, but it could process host objects as well. Since the beginning, we can see that dual nature of JavaScript: it has a big built-in functionality, and at the same time, that functionality is extended through its access to host’s APIS. For example: Math and parseInt are built-in objects, so they belong to the language specificaition itself, but the object ‘document’ is a host object, accessible through the Brower’s DOM API.



The set of reserved words or keywords had only 16 elements, and the future reserved keywords had another 16 elements as well. I can see the old friends new, var, this, typeof, function, delete, void, etc. From the origial first set of keyword, only with has been deprecated 😿. Reading the future reserved words like switch, case, default, export or class, it was clear that the near future of JavaScript already had a path: exceptions, exception management, classes (ala JavaScript of course), modules and enumerations.



The following are the JavaScript Keywords in 1997:




  break     for       new     var
  continue  function  return  void
  delete    if        this    while
  else      in        typeof  with



The following are the future reserved words by 1997:




  case  debugger  export    super
  catch default   extends   switch
  class do        finally   throw
  const enum      import    try



The set of operators included classic arithmetic, logical and relational ones; the typical bitwise operators, and the classical prefix and postfix ones. We see in the operators and keywords the influence of Java, and other languages of the C family. Here is the complete table:




  =     >     <     ==    <=    >=
  !=    ,     !     ~     ?     :
  .     &&    ||    ++    --    +
  -     *     /     &     |     ^
  %     <<    >>    >>>   +=    -=
  *=    /=    &=    |=    ^=    %=
  <<=   >>=   >>>=  (     )     {
  }     [     ]     ;



Another feature of JavaScript version 1997 was automatic semicolon insertion in some cases. Also, as were mentioned above, objects had four property attributes: ReadOnly, DontEnum, DontDelete and Internal.



If the property of some object had the ReadOnly set true, then basically converted it to a const property. Although the specificaition said that in some cases, that constant property may change over time. The attribute DontEnum turned the property into a non enumerable, so it was not enumerante in a for-in loop. if DontDelete was set in true, then that property became undeletable under the delete keyword. Finally, Internal properties were, as the name suggests, internal properties of objects. Such properties have no name and were not directly accessible from JavaScript itself, i.e. ther were not exposed to the language. In the specificaition, Internal properties where written within double squared brackets as it is even today: [[ property ]]



By 1997, JavaScript had a unique global object which was created before control entered any execution context. Initially, the global object had the following built-in objects: Math, String, Date, parseInt, etc., and they had the attribute DontEnum. In such global object, host entities like the window object lived there. Other objects JavaScript had were: Function, Constructor, Prototype, Instance object, Array, String, Boolean, Number, Math and Date. JavaScript had the basic while, for, for-in and if statements.



A picture of an old green car.
Photo by Brooke Balentine on Unsplash


The Execution Context



The 10th point of the first ECMAScript specificaition was dedicated to ‘execution contexts’. The section starts with the following sentence:



'When control is transferred to ECMAScript executable code, we say that control is entering an execution context. Active execution contexts logically form a stack. The top execution context on this logical stack is the running execution context.'



When JavaScript starts executing scripting code the call stack activates an execution context a.k.a stack frame. If another executable code starts its execution, a new execution context is created or activated on top of the first one, and son on. When the executable code at the top of the stack finish its execution, then that execution context is popped out of the stack and the previous execution context is now the top one.



The following illustarion is an abstract model of the execution context stack.

An illustration of the JavaScript's execution stack.


By 1997, JavaScript had five types of executable code:





Each execution context has an associated object called the ‘variable object’. Variables declared in the source text are added as properties of the variable object. For global and eval code, functions defined in the source text are added as properties of the variable object. For function, anonymous, and implementation-supplied code, parameters are added as properties of the variable object.



Another object associated with execution contexts is the ‘scope chain’. Every execution context has one scope chain assotiated with it. When scope chain is a list of objects that are searched when binding an identifier with some value. When the control leaves the execution context, popped out of the stack, its scope chain is destroyed. The scope chain allows to have a contextualized map of identifiers in its own scope. The result of binding an identifier is always a value of type Reference with its member name component equal to the identifier string.



If the control enters an execution context for a declared function code, anonymous code or implementation-supplied code, an object called the ‘activation object’ is created and is associated with that execution context. The activation object is initialized with a property named ‘arguments’ with attribute ‘DontDelete’. This object can be accessed from inside a function with the identifier ‘arguments’. For example:




  var fn = new Function('val', 'console.log(arguments); console.log(val);');
  fn(46); // Prints first ==> Arguments { 0: 46 }, then Prints ==> 46



There is also a this value associated with every execution context. The this value depends on the caller and type of code being executed and is determined when control enters the execution context. The this value associated with an execution context is immutable.



When the control enters an execution context for declared function code, anonymous code or implementation-supplied code, an ‘arguments object’ is declared and initialized as follows:





The this value



When control enters an execution context, the scope chain is created and initialized, variable instantiation is performed, and the this value is determined. The initialization of the scope chain, variable instantiation, and the determination of the this value depend on the type of code being entered. The following list illustrate the determination of this.





The full specificaition is worth read it because it gives very well grounded knowledge about ECMAScript. For now, I can stop here and conclude this seed.



Conclusion



The first specificaition of JavaScript was an important milestone it its history. The language was liberated of verdors, opened and accessible to the world, and had defined a common standard for everyone. Today, as 2025, JavaScript is one of the technologies that powers the Web, the most important human network information ever created.





Linked Seeds



External Links