Useful links:
Table of contents
- Beginning
- getPrototypeOf / setPrototypeOf
- __proto__
- Object.create
- Prototype chains
- Function prototypes
- Prototype inheritance
- Global Objects
- ES6 Classes
- Extensions
- Quiz
Beginning
const a = {};What properties does this object have?
None? Let’s try to log it in browser.

Object a has [[Prototype]] . What is it? It’s just a hidden property. Value of this property is link to an object.
In our case value of [[Prototype]] is link to Object.prototype. What is Object.prototype?

Just an object that’s have methods like toString() and etc (check photo).
What does this connection between object a and Object.prototype mean?
const a = {};
console.log(a.toString());Will there be a mistake? No. Why? JS engine like
Okay I should execute toString in a. Let’s check a. a doesn’t have field toString, so let’s go to prototype of a object.
It’s link to Object.prototype. Okay, I found toString in Object.prototype, let’s execute it. Engine checks all prototype chain.
If object doesn’t have some field, engine go to prototype. If prototype doesn’t have filed - engine will check prototype of prototype until it finds
this field or the prototype will be null. Prototype of Object.prototype is null. Don’t believe me? How to see prototype of something via JS but not dev tools?
getPrototypeOf / setPrototypeOf
These methods appeared in ES5. getPrototypeOf(obj) returns prototype of obj. setPrototypeOf(obj, anotherObj), now prototype of obj is anotherObj
const a = {
print: () => console.log("Hello")
}
const b = {};
console.log(Object.getPrototypeOf(a) === Object.getPrototypeOf(b));
Object.setPrototypeOf(b, a);
console.log(Object.getPrototypeOf(a) === Object.getPrototypeOf(b));
b.print();Show output
truefalse
Hello
__proto__
This property appeared in ES6. Use it instead of getPrototypeOf/setPrototypeOf.
const a = {
print: () => console.log("Hello")
}
const b = {};
console.log(a.__proto__ === b.__proto__);
b.__proto__ = a;
console.log(a.__proto__ === b.__proto__);
b.print();Show output
truefalse
Hello
Object.create
Object.create(...); creates a new object associated with the object we specified.
const B = Object.create(A); - prototype of B is A.
Prototype chains
Thanks to prototype, we can delegate behaviour to someone with whom we are connected by a prototype
const Parent = {
name: "Parent",
doSomething: function() {
console.log("Method from Parent, but name is taken from " + this.name)
}
}
const ChildOfParent = Object.create(Parent);
ChildOfParent.name = "Child of Parent";
const ChildOfChild = Object.create(ChildOfParent);
ChildOfChild.name = "Child of Child";
ChildOfChild.doSomething();Show output
Method from Parent, but name is taken from Child of ChildFunction prototypes
By default, all functions have a public, non-enumerable property called prototype.
function Foo() {
// ...
}
Foo.prototype; // { }Not a very good name. The prototype field (Foo.prototype) that appears in the function
and the prototype of the function itself (Foo.__proto__) are different things
function Foo() {
// ...
}
console.log(Foo.prototype === Foo.__proto__); // False!!!!!Each object that is constructed via new FunctionName() syntax is given a link to the function
prototype (FunctionName.prototype) by the its prototype (constructedObject.__proto__)
function Person() {}
const person = new Person();
console.log(person.__proto__ === Person.prototype);
Person.prototype also has a constructor filed references the function itself

We want the person object to have a name
function Person(name) {
this.name = name;
}
const person = new Person("Ksenia");
console.log(person);
console.log(Person.prototype);
Each object will have a `name` field inside itself.
But we want each instance of Person to have a greeting method
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log("Hello, my name is " + this.name);
}
const person = new Person("Ksenia");
console.log(person);
console.log(person.sayHello());
console.log(Person.prototype);
Prototype inheritance
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.mainInfo = function() {
console.log(`Main info: ${this.name}, ${this.age}`);
}
function Student(name, age, department) {
Person.call(this, name, age);
this.department = department;
}
Student.prototype = Object.create(Person.prototype);
// There is no constructor property in Student. you need
// to create it yourself
// Student.prototype.constructor = Student;
Student.prototype.educationInfo = function() {
console.log(`Education info: ${this. department}`);
}
const p = new Person("Ksenia", 19);
const s = new Student("Ksenia", 19, "Languages");
p.educationInfo() // error
s.educationInfo() // okGlobal objects
There are built-in objects in js (Object, Array, RegExp, Number, etc.)
const a = []; // Equal to const a = new Array();When we create an instance of such “classes”, the __proto__ object refers to
Class.prototype. And each Class.prototype refers to Object.prototype
const a = [];
console.log(a.__proto__ === Array.prototype); // true
console.log(a.__proto__.__proto__ === Object.prototype); // true
const b = 43;
console.log(b.__proto__ === Number.prototype); // true
console.log(b.__proto__.__proto__ === Object.prototype); // trueIf you can’t understand why primitive have __proto__ check this
ES6 Classes
Just syntactic sugar for prototypes. MDN
Extensions
- Loop
const a = {};
a.__proto__ = a; // TypeError: Cyclic __proto__ value- Right constructor
function Foo() {
/* .. */
}
Foo.prototype = {
/* .. */
};
Object.defineProperty(Foo.prototype, "constructor", {
enumerable: false,
writable: true,
configurable: true,
value: Foo,
});Quiz
- True or false
const a = {};
const b = {};
console.log(a.__proto__ === b.__proto__);Show answer
True- True or false
const a = {};
const b = [];
console.log(a.__proto__ === b.__proto__);Show answer
False- True or false
const a = {};
const b = [];
console.log(a.__proto__ === b.__proto__.__proto__);Show answer
True- True or false
class A {};
function B() {};
console.log(A.__proto__ === B.__proto__);Show answer
True- True or false
function Kek() {
this.hello = function() {
console.log("hello");
}
}
const a = new Kek();
const b = new Kek();
console.log(a.hello === b.hello);Show answer
False- True or false
function Kek() {}
Kek.prototype.hello = function() {
console.log("Hello");
}
const a = new Kek();
const b = new Kek();
console.log(a.hello === b.hello);Show answer
True- True or false
function Kek() {
this.hello = function() {
console.log("hello");
}
}
Kek.prototype.hello = function() {
console.log("Hello");
}
const a = new Kek();
const b = new Kek();
console.log(a.hello === b.hello);Show answer
False- Console output
Object.prototype.toString = function() { console.log("KEK") }
const a = {};
a.toString();Show answer
KEK- Console output
Object.prototype.toString = function() { console.log("KEK") }
const a = {
toString: () => console.log("LOL"),
};
a.toString();Show answer
LOL- Console output
Object.prototype.toString = () => console.log("KEK");
const a = [1, 2, 3];
console.log(a.toString());Show answer
1, 2, 3- Console output
Array.prototype.toString = () => console.log("KEK");
const a = [1, 2, 3];
a.toString();