+ - 0:00:00
Notes for current slide
Notes for next slide

JavaScript Prototypes

1 / 15

Summary

JavaScript Prototypes

Learn about prototypal inheritance in JavaScript.

This material is part of the mobile development course for Media Engineering.

You will need

  • Google Chrome (recommended, any browser with developer tools will do)

Recommended reading

2 / 15

Prototypal inheritance

JavaScript Prototypes

JavaScript is a little different than class-based languages like Java or C++ when it comes to inheritance. In JavaScript, the only constructs when it comes to inheritance are objects.

Objects Inherit From Other Objects

While this is often considered to be one of JavaScript's weaknesses, the prototypal inheritance model itself is, in fact, more powerful than the classic model. It is, for example, fairly trivial to build a classic model on top of a prototypal model.

3 / 15

The prototype chain

JavaScript Prototypes > Prototypal inheritance

Each object has a private property which holds a link to another object called its prototype. That prototype object has a prototype of its own, and so on until an object is reached with null as its prototype. By definition, null has no prototype, and acts as the final link in this prototype chain.

let o = {};
console.log(o.__proto__); // {}
console.log(o.__proto__.__proto__); // null
console.log(Object.getPrototypeOf(o)); // {}
console.log(Object.getPrototypeOf(Object.getPrototypeOf(o))); // null

Nearly all objects in JavaScript are instances of Object which sits on the top of a prototype chain:

let o = {};
console.log(Object.getPrototypeOf(o) === Object.prototype); // true

When trying to access a property of an object, the property will not only be sought on the object but also on the prototype of the object, the prototype of the prototype, and so on until either a property with a matching name is found or the end of the prototype chain is reached.

4 / 15

Creating plain JavaScript objects

JavaScript Prototypes > Prototypal inheritance

There are 3 ways to create objects in JavaScript.

The first way is to create a plain or literal object with curly braces, like so:

const person = { firstName: 'Bob', lastName: 'Page' };
console.log(person.firstName); // "Bob"
console.log(person.foo); // undefined
// The prototype of "person" is "Object.prototype".
let prototypeOfPerson = Object.getPrototypeOf(person);
console.log(prototypeOfPerson === Object.prototype); // true
// "Object.prototype" is the top of the inheritance chain. Its prototype is null.
let prototypeOfObject = Object.getPrototypeOf(Object.prototype);
console.log(prototypeOfObject === null); // true

Note that when we tried to access foo, a property that doesn't exist on person or on Object.prototype, we got undefined.

5 / 15

Creating objects with Object.create

JavaScript Prototypes > Prototypal inheritance

The second way to create objects is using Object.create, which creates a new object with the specified prototype.

This means that our new object, instead of having Object.prototype as its prototype, will have the object we passed to Object.create as its prototype:

const person = { firstName: 'Bob', lastName: 'Page' };
// Create an object with a prototype.
const child = Object.create(person);
// The prototype of "child" is "person".
let prototypeOfChild = Object.getPrototypeOf(child);
console.log(prototypeOfChild === person); // true
// The prototype of "person" is "Object.prototype".
let prototypeOfPerson = Object.getPrototypeOf(person);
console.log(prototypeOfPerson === Object.prototype); // true

6 / 15

Accessing properties in a prototype chain (part 1)

JavaScript Prototypes > Prototypal inheritance > Creating objects with Object.create

But what can we do with that object?

const person = { firstName: 'Bob', lastName: 'Page' };
// Create an object with a prototype.
const child = Object.create(person);
child.age = 12;
console.log(child.age); // 12
console.log(child.firstName); // "Bob"
console.log(child.foo); // undefined

This is what happens when you access child.age:

Obviously, we can retrieve that property since we just added it to child.

7 / 15

Accessing properties in a prototype chain (part 2)

JavaScript Prototypes > Prototypal inheritance > Creating objects with Object.create

But what can we do with that object?

const person = { firstName: 'Bob', lastName: 'Page' };
// Create an object with a prototype.
const child = Object.create(person);
child.age = 12;
console.log(child.age); // 12
console.log(child.firstName); // "Bob"
console.log(child.foo); // undefined

This is what happens when you access child.firstName:

child doesn't have a firstName property, so JavaScript will move on to the next object in the prototype chain, and check if that object has it. Since person is the prototype of child, and it has a firstName property, we get its value.

8 / 15

Accessing properties in a prototype chain (part 3)

JavaScript Prototypes > Prototypal inheritance > Creating objects with Object.create

But what can we do with that object?

const person = { firstName: 'Bob', lastName: 'Page' };
// Create an object with a prototype.
const child = Object.create(person);
child.age = 12;
console.log(child.age); // 12
console.log(child.firstName); // "Bob"
console.log(child.foo); // undefined

This is what happens when you access child.foo:

In this case, neither child, person nor Object.prototype have a property called foo, so after moving all the way up the prototype chain and having found no matching property, JavaScript returns undefined.

9 / 15

Overwriting a parent prototype's property

JavaScript Prototypes > Prototypal inheritance > Creating objects with Object.create

What happens if you add a property with the same name to the child object?

const person = { firstName: 'Bob', lastName: 'Page' };
// Create an object with a prototype.
const child = Object.create(person);
child.firstName = 'Megan';
console.log(child.firstName); // "Megan"
console.log(child.lastName); // "Page"

When you access child.firstName, it returns its own property:

When you access child.lastName, it returns its prototype's property:

10 / 15

Creating objects with a constructor function

JavaScript Prototypes > Prototypal inheritance

function Person(first, last) {
this.first = first;
this.last = last;
}
// Check that our function has an associated prototype object.
console.log(typeof(Person.prototype)); // "object"
// Create an object by calling the function as a constructor.
const child = new Person('Bob', 'Page');
let prototypeOfChild = Object.getPrototypeOf(child);
console.log(prototypeOfChild === Person.prototype); // true
let prototypeOfPerson = Object.getPrototypeOf(Person.prototype);
console.log(prototypeOfPerson === Object.prototype); // true

Every function has an associated prototype object which you can access by its prototype property. When you use that function as a constructor with new, the prototype of the created object will be the function's prototype object.

11 / 15

What does this mean?

JavaScript Prototypes > Prototypal inheritance

Let's combine two of the important things we just learned:

  • When accessing a property that doesn't exist on an object, JavaScript will look up the prototype chain and attempt to find it on the object's prototype, the prototype's prototype, and so on.
  • When creating an object by calling a constructor function, the prototype of the created object will be the function's associated prototype object.

Wait, what?

This means that if we attach things to a function's prototype object, these things will be available on any object constructed with that function.

12 / 15

Implementing a class-like structure with prototypes

JavaScript Prototypes

Welcome to your first JavaScript-class-without-a-class:

// Define a "class".
function Person(first, last) {
this.first = first;
this.last = last;
}
// Add a "method" to the "class".
Person.prototype.getFullName = function() {
return `${this.first} ${this.last}`;
};
// Construct an object.
const person = new Person('Bob', 'Page');
// Access properties like before.
console.log(person.first); // "Bob"
// Call a method.
console.log(person.getFullName()); // "Bob Page"

13 / 15

The value of this

JavaScript Prototypes > Implementing a class-like structure with prototypes

Note that when calling a function on an object, the keyword this always refers to the object the function was called on.

const o = {
value: 24,
getValue: function() {
return this.value
}
};
console.log(o.getValue()); // 24
function Foo() {
this.value = 42;
}
Foo.prototype.getValue = function() {
return this.value;
};
const o = new Foo();
console.log(o.getValue()); // 42

By the way, it's best to use the second structure rather than the first. Why? Because in the first example, a new function will be created every time you create an object this way. In the second example, only one getValue function is defined and attached to the prototype, and it's reused for every object that's an instance of Foo.

14 / 15

Summary

JavaScript Prototypes

Learn about prototypal inheritance in JavaScript.

This material is part of the mobile development course for Media Engineering.

You will need

  • Google Chrome (recommended, any browser with developer tools will do)

Recommended reading

2 / 15
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow