Search code examples
javascriptecmascript-5

Why is `const` a reserved keyword in JS but `let` isn't


Looking at JS Reserved words (MDN), it looks like new features are introduced in backwards-compatible manner, meaning var let = 0, async = 1, await = 2; is a valid expression, at least outside strict mode. See: Why are await and async valid variable names? and Why `let` isn't specified as reserved keyword in the spec

However, const is an actual keyword, so you cannot do var const = 0; (see: this post).

var let = 100; // OK
var const = 100; // SyntaxError: Cannot use the keyword 'const' as a variable name.

What bugs me is: why? I assume it means const was already reserved years before let/const came to be, but what meaning did it have back then? Was it just reserved for future intentions?


Solution

  • I assume it means const was already reserved years before let/const came to be?

    Yes. You can find it as a reserved word since ECMAScript 1.

    But what meaning did it have back then? Was it just reserved for future intentions?

    Yes:

    Future Reserved Words
    The following words are used as keywords in proposed extensions and are therefore reserved to allow for the possibility of future adoption of those extensions.

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

    Many of these were used in later versions of the language, like switch/case/default in ES3, try/catch/finally/throw in ES3, class/extends/super in ES6, export/import in ES6, do (with while) in ES3, the debugger statement in ES5, and const in ES6. enum is the only keyword that has been unconditionally reserved for the future in all versions of the language so far.

    ECMAScript 2 added even more Java-like reserved keywords, the list from back then:

    abstract  do import short
    boolean   double      instanceof  static
    byte      enum        int         super
    case      export      interface   switch
    catch     extends     long        synchronized
    char      final       native      throw
    class     finally     package     throws
    const     float       private     transient
    debugger  goto        protected   try
    default   implements  public      volatile
    

    ES3 implemented a few those.

    ES5 then removed some of the Java-isms like primitive type names and method modifiers, but also introduced some new reserved keywords (let, yield) and made a distinction in strict mode:

    FutureReservedWord :: one of
    class  enum    extends  super
    const  export  import 
    

    The following tokens are also considered to be FutureReservedWords when they occur within strict mode code:

    implements  let      private    public  yield
    interface   package  protected  static
    

    ES6 implemented classes and modules, leaving only enum, and introduced await as a reserved keyword in modules only. The rules of reserved keywords got only more complicated since, so that they are no longer described in the lexical grammar but rather as static semantic restrictions.