Dominik Lubański
const parent = { a: 1 };
const child = Object.create(parent);
child.a++;
console.log(child.a, parent.a);
// 1, 1
console.log(child.a, parent.a);
// 2, 1
const parent = { a: { b: 1 } };
const child = Object.create(parent);
child.a.b++;
console.log(child.a.b, parent.a.b);
// 1, 1
console.log(child.a.b, parent.a.b);
// 2, 2
const parent = {
get a() { return parent._a || 1 },
set a(val) { parent._a = val },
};
const child = Object.create(parent);
child.a++;
console.log(child.a, parent.a);
// 1, 1
console.log(child.a, parent.a);
// 2, 2
JavaScript is a bit confusing for developers experienced in class-based languages (like Java or C++), as it is dynamic and does not provide a class implementation per se.
JS creates a link between two objects, where one object can essentially delegate property/function access to another object.
Kyle Simpson / You-Dont-Know-JS
"Delegation" is a much more accurate term for JavaScript's object-linking mechanism.
Every object has an internal property called [[Prototype]], which links to other object or null:
const a = {};
// or
const a = Object.create(Object.prototype);
// a --> Object.prototype --> null
Object.getPrototypeOf(a));
// Object.prototype
a.__proto__;
// Object.prototype
a.__proto__.__proto__;
// null
const parent = { a: 1 };
const child = Object.create(parent);
const parent = { a: { b: 1 } };
const child = Object.create(parent);
// child.a;
child.[[GET]]('a', child);
// child.a.b
tempA = child.[[GET]]('a', child);
tempA.[[GET]]('b', tempA);
object.[[GET]](property, receiver)
const parent = { a: 1 };
const child = Object.create(parent);
const parent = { a: { b: 1 } };
const child = Object.create(parent);
// child.a++;
tempA = child.[[GET]]('a', child);
child.[[SET]]('a', tempA + 1, child);
// child.a.b++
tempA = child.[[GET]]('a', child);
tempB = tempA.[[GET]]('b', tempA);
tempA.[[SET]]('b', tempB + 1, tempA);
object.[[SET]](property, value, receiver)
function Library() {
this.value = 1;
};
Library.prototype.getValue = function getValue() {
return this.value;
};
const library = new Library();
library.getValue(); // 1
Many libraries uses constructor pattern:
Object.getPrototypeOf(library) === Library.prototype;
// library
// -> Library.prototype -> Object.prototype -> null;
function Library() {};
typeof Library.prototype;
// "object"
Object.getPrototypeOf(Library.prototype);
// Object.prototype
Library.prototype.constructor === Library;
// true
Library.prototype is special a property, which reference to object used as a prototype of constructor instance:
function Library() {};
typeof Library === 'function'; // true
Library instanceof Object; // true
Function has own type, but it is still an ordinary object:
// Prototype chain:
// Library -> Function.prototype -> Object.prototype
Object.getPrototypeOf(Library);
// Function.prototype
Object.getPrototypeOf(Function.prototype);
// Object.prototype
// when calling with 'new'
function Library() {
this = Object.create(Library.prototype);
this.value = 1;
return this;
};
function Library() {
this.value = 1;
};
new operator calls function with special behavior:
function Library() { // ... };
Library.prototype.options = { value: 1 };
const a = new Library();
const b = new Library();
// User assumes that he changes only own options
a.options.value++;
a.options.value === b.options.value;
// true
Sharing reference to object in prototype:
...the class keyword is introduced in ES6, but is syntactical sugar, JavaScript remaining
prototype-based
class Library {
constructor() {
this.value = 1;
}
getValue() {
return this.value;
}
}
function Library() {
this.value = 1;
};
Library.prototype.getValue =
function () {
return this.value;
};
class syntax still uses prototype:
typeof Library; // "function"
typeof Library.prototype.getValue; // "function"