Чистые объекты и классы

Используйте property descriptors (дескрипторы свойств) для создания полей только для чтения

"use strict"

var person = {
    firstName : "John",
    lastName: "Smith"
};

Object.defineProperty(person, 'age', {
    value: 28,
    writable: false,
    enumerable: true,
    configurable: false
})

console.log(person);
person.age = 44;
console.log(person);

Используйте ES6 наследование вместо прототипного наследования

function Pet(name) {
    this.name = name;
}

Pet.prototype.eat = function() {
    console.log(`${this.name} is eating`);
}

function Dog(name, breed) {
    Pet.call(this, name);
    this.breed = breed;
}

Dog.prototype = Object.create(Pet.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.play = function () {
    console.log(`${this.name} is playing`);
}

let max = new Dog("Max, "Golden Retriever");
max.eat();
max.play();
console.log(max);

Нам понадобилось многовато написать для такой простой задачи.
Посмотрим какой расклад при использовании ES6 classes

class Pet {
    constructor(name) {
        this.name = name;
    }

    eat() {
        console.log(`${this.name} is eating`);
    }
}

class Dog extends Pet {
    constructor(name, breed) {
        super(name);
        this.breed = breed;
    }

    play() {
        console.log(`${this.name} is playing`);
    }
}

let max = new Dog('Max', 'Golden Retriever');
max.eat();
max.play();
console.log(max);

Используйте Object.freeze вместе с const при создании неизменяемых объектов

Если Вам действительно нужны неприкасаемые объекты, то const это не помошник в этом.

const config = {
    fbApiKey: 'snfa9f7yxfe87sef0932jlk',
    googleApiKey: '390ufe09s087rv998v7s98',
    linkedInApiKey: 'es898e6f93kj2rnlkj23h4ljh23'
};

console.log(config);
config.googleApiKey = '';
console.log(config);

Мы можем добиться желаемого всего одной строчкой.

Object.freeze(config);

console.log(config);
config.googleApiKey = '';
console.log(config);

Теперь мы не сможем, ни добавить, ни удалить значение из конфига.