Execute Program

Modern JavaScript: Class Scoping

Welcome to the Class Scoping lesson!

This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!

  • We usually define classes at the top level of a module. However, classes follow the same scoping rules as regular variables. We can define them inside a function, or even inside a conditional.

  • >
    function createKoko() {
    class Gorilla {
    constructor(name) {
    this.name = name;
    }
    }
    return new Gorilla('Koko');
    }
    createKoko().name;
    Result:
    'Koko'Pass Icon
  • >
    function createGorilla(name) {
    if (name === undefined) {
    return undefined;
    } else {
    class Gorilla {
    constructor(name) {
    this.name = name;
    }
    }
    return new Gorilla(name);
    }
    }
    [createGorilla(undefined), createGorilla('Koko').name];
    Result:
    [undefined, 'Koko']Pass Icon
  • Just to be clear: there are very few cases where a class should be defined in a function. There are even fewer (and maybe none) where a class should be defined inside a conditional. But JavaScript allows us to do these things!

  • Here's a much better version of the previous code example, where the Gorilla class is defined at the top level of the module. Notice how much easier it is to read now that Gorilla is defined separately.

  • >
    class Gorilla {
    constructor(name) {
    this.name = name;
    }
    }

    function createGorilla(name) {
    if (name === undefined) {
    return undefined;
    } else {
    return new Gorilla(name);
    }
    }

    [createGorilla(undefined), createGorilla('Koko').name];
    Result:
    [undefined, 'Koko']Pass Icon
  • A class defined dynamically (like inside of a function or even inside of an if) can see all of the variables that are currently in scope.

  • In the next example, notice that the class's constructor doesn't take a name argument. Instead, the class is "capturing" the containing function's name argument!

  • >
    function createGorilla(name) {
    class Gorilla {
    constructor() {
    this.name = name;
    }
    }
    return new Gorilla();
    }
    createGorilla('Michael').name;
    Result:
    'Michael'Pass Icon
  • We can't define a class inside another class. That causes an error, whether we use the class or not.

  • >
    class Zoo {
    class Gorilla {
    constructor(name) {
    this.name = name
    }
    }
    }
    Result:
    SyntaxError: on line 2: Unexpected tokenPass Icon
  • Classes are only visible inside the scope where they were defined, just like variables defined with let or const. If we try to reference a class outside of its scope, we'll get an error.

  • >
    if (true) {
    const x = 1;
    }
    x;
    Result:
    ReferenceError: x is not definedPass Icon
  • >
    function createGorilla() {
    class Gorilla {
    constructor(name) {
    this.name = name;
    }
    }
    return new Gorilla('Koko');
    }
    new Gorilla('Koko');
    Result:
    ReferenceError: Gorilla is not definedPass Icon
  • >
    if (true) {
    class Cat { }
    }
    new Cat();
    Result:
    ReferenceError: Cat is not definedPass Icon