As classes JavaScript contam com dois métodos especiais: um com o prefixo get que tem a função de retornar um valor, e outro precedido pela palavra set que serve para atribuir um valor. Ambos funcionam como se fossem uma propriedade da classe. Podemos ver melhor no exemplo abaixo:

class Pessoa {
    constructor () {
        this.data = {}
    }

    cpfIsValid (value) {
        return /^\d\.\d\.\d\-\d$/.test(value)
    }

    get cpf () {
        // verifica se a propriedade não existe no atributo this.data da classe
        if (!this.data.hasOwnProperty('cpf')) {
        return undefined
        }
        // retorna o valor da cpf
        return this.data.cpf
    }

    set cpf (value) {
        if (!this.cpfIsValid(value)) {
        throw new Error('numero de cpf invalido')
        }

        this.data[ 'cpf' ] = value
    }
}

const pessoa = new Pessoa()

pessoa.cpf = '999.999.999-99'

console.log(pessoa.cpf) // 999.999.999-99

Neste exemplo reescrevemos a classe criando um único atributo na classe chamado data na linha 3 onde definimos seu valor inicial como um objeto vazio. Este atributo tem como função armazenar propriedades que serão utilizadas na classe.

Entre as linhas 10 a 17 definimos um getter: método especial que serve para recuperar o valor de um item. Perceba na linha 32 que acessamos a propriedade cpf como um atributo da classe.

Nas linhas 19 a 25 é definido o método setter, um outro método especial que serve para definir um valor. Perceba que na linha 30 utilizamos o setter cpf como se estivéssemos definindo um valor em um atributo.