В данном примере вы, как мне кажется, путаете
инкапсуляцию и сокрытие данных
Инкапсуляция - это прежде всего, сокрытие сложности системы, как правило, через объединение логики и данных. Сокрытие самих данных - не всегда обязательный элемент инкапсуляции.
Javascript использует прототипное наследование, и в его реализации, традиционно, с сокрытием данных есть некоторые проблемы. Даже в "строго-типизированных" надстройках (например, в typescript), где в систему классов добавлены ключевые слова private и protected, защищенные свойства объектов все равно будут доступны извне на рантайме:
// TypeScript
class Foo {
private bar = "lol"; // приватное поле класса
baz = 42;
}
const foo = new Foo();
console.log((foo as any).bar) // "lol"
Если сокрытие данных на рантайме все-таки необходимо, его можно добиться с помощью замыканий и символов:
const factory = () => {
// используем замыкание, чтобы ограничить область видимости
const privateProp = Symbol();
function Foo() {
// используем символ как идентификатор поля
this[privateProp] = "lol";
this.bar = 42;
}
return new Foo()
}
const foo = factory();
// foo[privateProp] использовать невозможно вне замыкания
console.log(foo.bar) // 42