DEV Community

Raul-Sebastian Mihăilă
Raul-Sebastian Mihăilă

Posted on

Prototypal noninheritance in Javascript

Everybody knows that the inheritance mechanism in Javascript is prototypal. Many also know that it's possible for an object to not have a prototype and therefore not inherit anything. But did you know that it's possible for an object to have a prototype but not inherit from it?

First of all, while the Javascript specification provides hints about what inheritance is, it doesn't fully define it. But how can we observe the inheritance mechanism? Well, we need an object with a prototype, see that the object doesn't have a property that the prototype has and then when we access that property on the object we get the same value that we would get if we accessed it on the prototype. We're also freezing the object and the prototype in order to make things look less dynamic.

const proto = {x: 1};
const obj = {};

Object.setPrototypeOf(obj, proto);

Object.freeze(proto);
Object.freeze(obj);

console.log(1, Object.getPrototypeOf(obj)); // proto
console.log(2, Object.getPrototypeOf(obj) === proto); // true
console.log(3, obj.hasOwnProperty('x')); // false
console.log(4, 'x' in obj); // true
console.log(5, proto.hasOwnProperty('x')); // true
console.log(6, proto.x); // 1
console.log(7, obj.x); // 1
console.log(8, obj.x === proto.x); // true

So basically we made eight observations here and we're looking to prove that it's possible for the last two observations to be different for a particular object, even if the first six are the same as in this example.

The answer is: proxies!

const proto = {x: 1};
const proxyTarget = {};

Object.setPrototypeOf(proxyTarget, proto);

const obj = new Proxy(proxyTarget, {
  get(proxyTarget, prop, receiver) {
    if (proto.hasOwnProperty(prop)) {
      return undefined;
    }

    return Reflect.get(proxyTarget, prop, receiver);
  }
});

Object.freeze(proto);
Object.freeze(obj);

console.log(1, Object.getPrototypeOf(obj)); // proto
console.log(2, Object.getPrototypeOf(obj) === proto); // true
console.log(3, obj.hasOwnProperty('x')); // false
console.log(4, 'x' in obj); // true
console.log(5, proto.hasOwnProperty('x')); // true
console.log(6, proto.x); // 1
console.log(7, obj.x); // undefined
console.log(8, obj.x === proto.x); // false

Top comments (0)