Prototypes & Inheritance in JavaScript - Exercise 3
Use Object.defineProperty() to control whether a property is writable, enumerable, or configurable.
const account = {};
Object.defineProperty(account, 'id', {
value: 42,
enumerable: true,
writable: false
});Properties created with defineProperty default to false for writable, enumerable, and configurable unless specified.
const settings = {};
Object.defineProperty(settings, 'mode', { value: 'safe' });
console.log(Object.keys(settings)); // []Use Object.defineProperty on the prototype and set enumerable: false.
function User(name) { this.name = name; }
Object.defineProperty(User.prototype, 'greet', {
value() { return `Hi, ${this.name}`; },
enumerable: false
});Changes can conflict with libraries, future platform methods, or other code sharing the same global prototype.
// Prefer a standalone helper:
function sum(values) {
return values.reduce((total, value) => total + value, 0);
}The method may live on a prototype, but a normal method call supplies the receiving object as this.
const actions = {
greet() { return `Hello, ${this.name}`; }
};
const user = Object.create(actions);
user.name = 'Mina';
console.log(user.greet());Use Object.setPrototypeOf sparingly and prefer creating the object with its final prototype. Freeze stable prototype objects when appropriate.
const permissions = Object.freeze({
canRead: true
});
const user = Object.create(permissions);
console.log(user.canRead);Every linked instance observes the change, which can create surprising behavior and make debugging difficult.
function Feature() {}
const first = new Feature();
const second = new Feature();
Feature.prototype.enabled = true;
console.log(first.enabled, second.enabled); // true trueIt is useful when many objects need shared behavior while keeping their own data separate and memory use low.
const workerMethods = {
work() { return `${this.name} is working`; }
};
const worker = Object.create(workerMethods);
worker.name = 'Sam';
console.log(worker.work());