JEP 203: Nashorn: Lexically-Scoped Variable & Constant Declarations

OwnerHannes Wallnoefer
Created2014/06/05 14:41
Updated2016/06/07 23:31
TypeFeature
StatusClosed / Delivered
Componentcore-libs / jdk.nashorn
ScopeJDK
Discussionnashorn dash dev at openjdk dot java dot net
EffortM
DurationS
Priority3
Reviewed byBrian Goetz, Jim Laskey
Endorsed byBrian Goetz
Release8u40
Issue8046038

Summary

Implement the lexically-scoped variable (let) and constant (const) declarations of the forthcoming ECMAScript 6 specification.

Goals

Non-Goals

This JEP is limited to the features listed above; it does not include any of the other new features of ECMAScript 6.

Motivation

The upcoming version 6 of the ECMAScript standard, code-named "Harmony", will be the first to support block scope for variable, constant, and function declarations. Previous versions of ECMAScript (including version 5, implemented by Nashorn) only provide the var keyword for variable declarations, which always uses the containing function body or program as scope, and does not allow the declaration of constants. ECMAScript 6 introduces two new keywords let and const to define variables and constants only within their lexical scope.

Lack of lexical scoping is widely recognized as one of the major flaws in current JavaScript. Therefore, support for let and const and lexical scoping ranks very high on the list of ECMAScript 6 features implemented by other JavaScript engines.

This feature has already been implemented in the V8 and Mozilla Spidermonkey JavaScript engines, and it is used by some Node.js modules. Therefore it has been requested by the Avatar.js team, among others.

Description

Up to version 5 of the ECMAScript standard, JavaScript only provides the var keyword to declare variables. One major problem with var is that variables are always scoped to the entire body of the containing function. For example, in the following code the variable a is defined everywhere in the function:

function f(x){
    if (x) {
        var a = 42;
    }
    // "a" is defined here
}

This can be very problematic if some of the code is meant to access a variable with the same name defined outside the function:

var a = 2;

function f(x) {
    // "a" is undefined here
    if (x) {
        var a = 42;
    }
    // "a" is 42 or undefined, depending on "x"
}

Using the let keyword introduced in ECMAScript 6 allows us to limit the declaration of a to its containing block:

let a = 2;

function f(x) {
    // "a" is 2 here
    if (x) {
        let a = 42;
    }
    // "a" is still 2
}

The second problem with var is its inability to define constants except for the very verbose Object.defineProperty method:

// Only way to define a constant in ECMAScript 5
Object.defineProperty(this, "CONSTANT", { writable: false, configurable: false, value 42 });

ECMAScript 6 significantly improves this by introducing the const keyword:

const CONSTANT = 42;

Like let, constants declared by const are limited to their containing lexical scope.

Testing

So far the official ECMAScript test suite, test262, does not cover ECMAScript version 6. We will have to come up with our own tests and see what is available on the net.

Risks and Assumptions

ECMAScript 6 ("Harmony") has not been finalized, so it's possible that there may be changes until the final standard is released. However, the current draft is pretty much frozen and any remaining changes are expected to be small or concerning corner cases.